2016-11-07 2 views
3

Я работаю над Python около 2 месяцев, поэтому у меня есть понимание этого.Создание матрицы из файла CSV

Моя цель - создать матрицу с использованием CSV-данных, а затем заполнить эту матрицу из данных в третьем столбце этого CSV-файла.

Я придумал этот код до сих пор:

import csv 

import csv 
def readcsv(csvfile_name): 
     with open(csvfile_name) as csvfile: 
     file=csv.reader(csvfile, delimiter=",") 

#remove rubbish data in first few rows 

     skiprows = int(input('Number of rows to skip? ')) 
      for i in range(skiprows): 
       _ = next(file) 

#change strings into integers/floats 

      for z in file: 
       z[:2]=map(int, z[:2]) 
       z[2:]=map(float, z[2:]) 
       print(z[:2]) 
     return 

После удаления мусора данных с указанным кодом, данные в файле CSV выглядит следующим образом:

Input: 
    1 1 51 9 3 
    1 2 39 4 4 
    1 3 40 3 9 
    1 4 60 2 . 
    1 5 80 2 . 
    2 1 40 6 . 
    2 2 28 4 . 
    2 3 40 2 . 
    2 4 39 3 . 
    3 1 10 . . 
    3 2 20 . . 
    3 3 30 . . 
    3 4 40 . . 
    . . . . . 

Выход должен выглядят так:

 1 2 3 4 . . 
    1 51 39 40 60 
    2 40 28 40 39 
    3 10 20 30 40 
    . 
    . 

В этом CSV-файле имеется несколько тысяч строк и столбцов, однако Меня интересуют только первые 3 столбца файла CSV. Таким образом, первый и второй столбцы в основном похожи на координаты для матрицы, а затем заполняют матрицу данными в третьем столбце.

После многих проб и ошибок я понял, что numpy - это способ пойти с матрицами. Это то, что я пытался до сих пор с примером данных:

left_column = [1, 2, 1, 2, 1, 2, 1, 2] 
    middle_column = [1, 1, 3, 3, 2, 2, 4, 4] 
    right_column = [1., 5., 3., 7., 2., 6., 4., 8.] 

    import numpy as np 
    m = np.zeros((max(left_column), max(middle_column)), dtype=np.float) 
    for x, y, z in zip(left_column, middle_column, right_column): 
     x -= 1 # Because the indicies are 1-based 
     y -= 1 # Need to be 0-based 
     m[x, y] = z 
    print(m) 

    #: array([[ 1., 2., 3., 4.], 
    #:  [ 5., 6., 7., 8.]]) 

Однако, это нереально для меня, чтобы указать все мои данные в моем сценарии для создания матрицы. Я попытался использовать генераторы, чтобы вытащить данные из моего CSV-файла, но для меня это не сработало.

Я узнал столько же, сколько мог, но, похоже, он требует, чтобы мои данные уже были в матричной форме, а это не так.

+0

Я не понимаю смысла последних двух столбцов. Первые три ясны ... (строка, столбец, значение) – Nikaidoh

ответ

1

Это мое решение, используя только библиотека csv и работа с индексом \ position в csv (Используя смещение, которое я использую его поддерживать память о текущей строке)

import csv 

with open('test.csv', 'r') as csvfile: 
    spamreader = csv.reader(csvfile, delimiter=',') 
    list_of_list = [] 
    j=0 
    lines = [line for line in spamreader] 
    for i in range(len(lines)): 
     list_ = [] 
     if(len(lines)<=i+j): 
      break; 
     first = lines[i+j][0] 
     while(first == lines[i+j][0]): 
      list_.append(lines[i+j][2]) 
      j+=1 
      if(len(lines)<=i+j): 
       break; 
     j-=1 
     list_of_list.append(list(map(float,list_))) 

maxlen = len(max(list_of_list)) 
print("\t"+"\t".join([str(el) for el in range(1,maxlen+1)])+"\n") 
for i in range(len(list_of_list)): 
    print(str(i+1)+"\t"+"\t".join([str(el) for el in list_of_list[i]])+"\n") 

В любом случае решение опубликовано Saullo изящнее

Это мой выход:

 1  2  3  4  5 

1  51.0 39.0 40.0 60.0 80.0 

2  40.0 28.0 40.0 39.0 

3  10.0 20.0 30.0 40.0 

я написал новая версия кода с итератором, поскольку csv слишком велик для установки в память

import csv 

with open('test.csv', 'r') as csvfile: 
    spamreader = csv.reader(csvfile, delimiter=',') 
    list_of_list = [] 

    line1 = next(spamreader) 
    first = line1[0] 
    list_ = [line1[2]] 
    for line in spamreader: 
     while(line[0] == first): 
      list_.append(line[2]) 
      try: 
       line = next(spamreader) 
      except : 
       break; 
     list_of_list.append(list(map(float,list_))) 
     list_ = [line[2]] 
     first = line[0] 

maxlen = len(max(list_of_list)) 
print("\t"+"\t".join([str(el) for el in range(1,maxlen+1)])+"\n") 
for i in range(len(list_of_list)): 
    print(str(i+1)+"\t"+"\t".join([str(el) for el in list_of_list[i]])+"\n") 

В любом случае, возможно, вам нужно работать над матрицей в кусках (и делать свопы), потому что, вероятно, данные не будут вписываться в массив 2d

+0

Эй, я попробовал запустить код, и в строке 7 произошла ошибка с «MemoryError». Есть предположения? – dizzyLife

+0

Вы использовали в качестве входных данных csv, который вы разместили ранее, или другой csv? может быть, больше? Я не тестировал его на большом примере – Nikaidoh

+0

, вероятно, ваш csv слишком велик, чтобы вписаться в память, поэтому вам нужно использовать итератор – Nikaidoh

3

Вы можете использовать scipy.sparse.coo_matrix чтобы загрузить эти данные очень удобно.

Работа с входом:

Input: 
    1 1 51 9 3 
    1 2 39 4 4 
    1 3 40 3 9 
    1 4 60 2 . 
    1 5 80 2 . 
    2 1 40 6 . 
    2 2 28 4 . 
    2 3 40 2 . 
    2 4 39 3 . 
    3 1 10 . . 
    3 2 20 . . 
    3 3 30 . . 
    3 4 40 . . 
    . . . . . 

Вы можете сделать:

l, c, v = np.loadtxt('test.txt', skiprows=1).T 
m = coo_matrix((v, (l-1, c-1)), shape=(l.max(), c.max())) 

Затем вы можете преобразовать coo_matrix к np.ndarray:

In [9]: m.toarray() 
Out[9]: 
array([[ 51., 39., 40., 60., 80.], 
     [ 40., 28., 40., 39., 0.], 
     [ 10., 20., 30., 40., 0.]]) 
+0

Эй, во-первых, спасибо за помощь. Я попытался запустить код, заменив test.txt на файл csv с именем file.csv, но я получил ошибку: подпроцесс IDLE не установил соединение. Либо IDLE не может запустить подпроцесс, либо личное программное обеспечение блокирует соединение. Является ли этот meman, я просто должен положить все данные в блокнот? – dizzyLife

+0

@ dizzyLife конечно, но убедитесь, что вы сохранили только действительные данные, в этом случае я сохранил только до третьего столбца, иначе вам нужно было бы: 'l, c, v = np.loadtxt (" file.csv ", skiprows = 1) .T [: 3,:]' для ограничения чтения до третьего столбца (при транспонировании до третьего ряда) –

+0

@dizzyLife также проверьте, не является ли ваш разделитель в файле 'csv' чем-то другим из пустых пространств. Если да, вам нужно передать 'delimiter =", "' в функцию 'loadtxt' (или другой символ-разделитель, который у вас есть) –

2

Вам следует серьезно подумать об использовании pandas. Это действительно идеально подходит для такого рода работ. Я не могу дать вам фактическое решение, потому что у меня нет данных, но я хотел бы попробовать что-то вроде следующего:

import pandas as pd 
df = pd.read_csv('test.csv', usecols=[0,1,2], names=['A', 'B', 'C']) 
pd.pivot_table(df, index='A', columns='B', values='C') 

Вторая строка импортирует данные в объект панды DataFrame (изменить имена в что-то более полезное для вашего приложения). Сводная таблица создает матрицу, которую вы ищете, и изящно обрабатывает любые отсутствующие данные.

+0

Спасибо за комментарий. Было бы полезно, если бы я отправил CSV-файл? Я не мог заставить его работать после многочисленных попыток. Ошибка: AttributeError: объект 'module' не имеет атрибута 'read_csv' – dizzyLife

+0

@ dizzyLife: Какую версию Pandas вы используете? Если вы импортировали pandas в качестве pd, введите «pd .__ version__» в python. Я использую pandas 0.18.0, так что, возможно, вам нужна новая версия pandas? –

+0

@ dizzyLife: Игнорировать предыдущий комментарий, read_csv был в пандах с самого начала. Вероятно, ваша ошибка означает, что pandas установлен неправильно. Выполняли ли «импорт pandas as pd» какие-либо исключения? –

Смежные вопросы