如何为numpy genfromtxt

时间:2015-10-20 09:30:47

标签: python arrays csv numpy

我找到了许多方法来输入带有文本条目的csv文件作为Python中的数值数组,例如thisthis,但没有一种情况我没有,也没有人为我工作。我也找不到the manual numpy或其他常用工具的答案,但也许它就在那里,我无法理解它。

我在这样的csv中有数据:

"experiment 1"
"var1","var2","var3","var4","var5"
"7","0","1","3","1"
"8","4","3","1","1"
"8","5","3","3","1"
"8","6","3","3","3"

我尝试使用

读取数据
dataArray = np.genfromtxt('Input Data/'+fileName,delimiter=',',skiprows=2)

我也尝试添加

.astype(np.float)
到最后。但在任何一种情况下我最终都是:

[[ nan  nan  nan  nan  nan]
[ nan  nan  nan  nan  nan]
[ nan  nan  nan  nan  nan]
[ nan  nan  nan  nan  nan]]

因为将数字列中的字符串转换为nan是genfromtxt根据文档应该做的事情。 converters还有一个genfromtxt参数,但我可以找到使用它的唯一示例来自文档:

converters = {3: lambda s: float(s or 0)}

我真的无法理解这种语法。假设内置转换器可以处理我的数据,为此编写转换器参数的正确语法是什么?如果转换器无法满足我的需求,有人知道如何读取这些数据吗?我预计这会非常简单,我会在5分钟内找到,但我现在浪费了几个小时。

5 个答案:

答案 0 :(得分:3)

使用列名称读取数据

要使用np.genfromtext,您应首先将文件读入字符串,删除所有"字符,然后使用cStringIO读取此字符串:

>>>import cStringIO
>>>with open ("123", "r") as myfile:
       data=myfile.read().replace('"', '')
>>>np.genfromtxt(cStringIO.StringIO(data), skip_header=1, delimiter=",", names = True)

array([(7.0, 0.0, 1.0, 3.0, 1.0),
       (8.0, 4.0, 3.0, 1.0, 1.0),
       (8.0, 5.0, 3.0, 3.0, 1.0),
       (8.0, 6.0, 3.0, 3.0, 3.0)], 
      dtype=[('var1', '<f8'), ('var2', '<f8'), ('var3', '<f8'), ('var4', '<f8'), ('var5', '<f8')]) 

您还可以使用pandas

>>>pd.read_csv(file, header=0, skiprows = 1).as_matrix()

   var1  var2  var3  var4  var5
0     7     0     1     3     1
1     8     4     3     1     1
2     8     5     3     3     1
3     8     6     3     3     3

在没有列名的情况下读取数据

您可以先将文件读取到包含字符串的数组中:

a = np.genfromtxt('filename', skip_header=2, delimiter=",", dtype = 'str')
print a

给出:

[['"7"' '"0"' '"1"' '"3"' '"1"']
 ['"8"' '"4"' '"3"' '"1"' '"1"']
 ['"8"' '"5"' '"3"' '"3"' '"1"']
 ['"8"' '"6"' '"3"' '"3"' '"3"']]

然后使用像这样的numpy将它转换为浮点数:

a = np.char.strip(a, '"').astype(float)
print a

给出了

[[ 7.  0.  1.  3.  1.]
 [ 8.  4.  3.  1.  1.]
 [ 8.  5.  3.  3.  1.]
 [ 8.  6.  3.  3.  3.]]

您还建议使用pandas。要在pandas DataFrame中阅读它,您可以这样做:

import pandas as pd
a = pd.read_csv('./test', header=None, skiprows = 2)
print a

给出:

   0  1  2  3  4
0  7  0  1  3  1
1  8  4  3  1  1
2  8  5  3  3  1
3  8  6  3  3  3

答案 1 :(得分:2)

经过更多的搜索,尝试和战斗,我设法找到了一种方法来做到这一点。

首先,为方便起见,我单独制作转换公式,并在genfromtxt命令中调用它:

convert = lambda x: float(x.strip('"') or -999)

lambda function做的是从每个条目中删除双引号字符(或者如果它为空或nan将其设置为-999),然后将条目转换为一个浮子。然后它进入genfromtext命令,如下所示:

dataArray = np.genfromtxt('Input Data/'+fileName,delimiter=',',skip_header=2,converters={0: convert,1: convert,2: convert,3: convert,4: convert},dtype=None)

这适用于这种特殊情况,但它有两个问题:(1)您必须分别为每个列指定转换器 - 我无法找到指定&#34; apply的方法对所有列&#34;。更好的方法是使用遍历所有列的迭代函数并将转换应用于所有列...然后THAT函数将指定要应用它的列至。如果可能的话,我不知道如何做到这一点。问题(2)是您无法与转换器一起读取标题。例如:

dataArray = np.genfromtxt('Input Data/'+fileName,delimiter=',',skip_header=1,names=True,converters={0: convert,1: convert,2: convert,3: convert,4: convert},dtype=None)  
如果数据上方的行有列标题,

应该有效,但是当从列中读入名称时,它不再是数组,而是元组列表。这可能是因为数据中的列名称也有引号,并且转换器未应用于它们。这应该没关系,因为它们不是数组的一部分,这是所有数字,但这似乎是genfromtxt的工作原理。也就是说,它似乎不是一个非常好/强大的方法来执行这项任务,当然它的记录很差,所以它不清楚它能做什么或能做什么&#39;做和如何让方法做这些事情。

我对将来遇到此问题的人的建议是寻找一种不同的方法来执行此功能。许多人建议pandas在其他问题中执行类似任务,但我不知道这种情况是否更好。目前这对我有用,但在不久的将来,它必须被更强大的csv阅读器取代,以生成numpy可以很容易地构建成阵列的文件格式。

答案 2 :(得分:0)

this will print you first two columns in the file
Since you have two headers you need to skip first to rows with next()

with open("data.csv", 'r') as f:
        r = csv.reader(f, delimiter=',')
        next(r, None)  # skip the header
        next(r, None)  # skip the header
        for row in r:
            print(row[0],row[1])

7 0
8 4
8 5
8 6

答案 3 :(得分:0)

当你说:

  

converters = {3:lambda s:float(s或0)}   我真的无法理解那种语法

来自Numpy文档:

  

转换器:dict,可选   将列号映射到将该列转换为float的函数的字典。例如,如果第0列是日期字符串:converters = {0:datestr2num}。转换器也可用于为丢失的数据提供默认值(但另请参见genfromtxt):converters = {3:lambda s:float(s.strip()或0)}。默认值:无

所以在示例中:

  

converters = {3:lambda s:float(s或0)}

这意味着转换器是一个python字典(python中字典的文字是{key:value],例如

dict_example = {1: "the position is 1"}

其中键为1,值为“位置为1”。

转换器是一个字典,其中键是文件中列的编号,值是转换,它将应用于该列的每个元素。函数在Python中用 lambda 表示(从技术上讲,它们是匿名函数,在其他地方查找文档)

所以

  

converters = {3:lambda s:float(s或0)}

将转换器定义为字典,其中键引用第3列,然后将函数 float 应用于该列的每个元素。

另一个技巧是 float 函数,其中包含。我们在这里使用的是运算符的shortcircuit

如果s为空或不是数字(请参阅更多详细信息here),则结果为false,而 false 结果为 0 ,结果为 0 。所以它是一种简洁的形式,将任何不是数字(甚至缺失)的东西转换为0.如果 s 是一个字符串,或短路并返回 s

答案 4 :(得分:0)

我找到了两个解决方案。 1.使用转换器 2.使用excel或LibreCalc。

  1. 转换器为我工作,但它们使用字典,因此您必须指定每一列。当它们是字符串时,对于保留特定列很有用,但不是一个很好的解决方案。
    import numpy as np;

myConverters = {}
myConverters[0] = lambda s:float(s.decode('ascii').strip('"')); #column zero is a number
myConverters[1] = lambda s:s; #column 1 is a string

filename = 'Spread of Disease population-density-table.csv';

data = np.genfromtxt(filename, skip_header= 6, #skip_footer=10, 
                     delimiter= ",", 
                     #names= True,
                     #dtype= str,
                     converters = myConverters,

                     )
print(data)

  1. 一个更简单的解决方案是在LibreCalc(excel)中打开文件并将其另存为.csv。这样会将文件保存为标准格式(“ no”)。

此后,一切照旧。