2016-11-07 113 views
3

我已經在Python上工作了大約2個月,所以我對它有了一個很好的理解。從CSV文件創建矩陣

我的目標是使用CSV數據創建矩陣,然後從該CSV文件的第3列中的數據填充該矩陣。

我想出了這個代碼迄今:

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文件中有大約幾千行和幾列,但是我只感興趣的是CSV文件的前3列。所以第一列和第二列基本上就像矩陣的座標,然後用第三列的數據填充矩陣。

經過大量的試驗和錯誤,我意識到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文件中提取數據,但對我來說效果不佳。

我儘可能多地學會了numpy,但它看起來好像它需要我的數據已經是矩陣形式,事實並非如此。

+0

我不明白最後兩列的意思。前三個是清楚的...(行,列,值) – Nikaidoh

回答

1

這只是用我的解決方案:

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

然後您可以將coo_matrixnp.ndarray轉換csv庫,並在csv中使用index \ position (使用偏移量我用十個分量內存的當前行)

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") 

無論如何,您可能需要在Matrix中進行大塊(並進行交換),因爲數據可能不適合二維陣列

+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 . . 
    . . . . . 

你可以這樣做:

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

嘿,首先感謝您的幫助。我試圖通過用名爲file.csv的csv文件替換test.txt來運行代碼,但我得到了錯誤: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') 

第二行的數據導入一個數據框大熊貓對象(更改名稱爲對您的應用程序更有用的東西)。數據透視表創建您正在查找的矩陣,並優雅地處理任何缺失的數據。

+0

感謝您的評論。如果我發送CSV文件會有幫助嗎?經過無數次嘗試後,我無法完成它的工作。錯誤是:AttributeError:'模塊'對象沒有屬性'read_csv' – dizzyLife

+0

@dizzyLife:你使用的是哪個版本的熊貓?如果您已將pandas導入爲pd,請將「pd .__ version__」鍵入python。我使用熊貓0.18.0,所以也許你需要更新的熊貓版本? –

+0

@dizzyLife:忽略之前的評論,read_csv從一開始就一直在熊貓。你的錯誤可能意味着熊貓安裝不正確。運行「import pandas as pd」是否會產生任何異常? –