2016-11-07 80 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”是否会产生任何异常? –