如何为numpy genfromtx设置字符串到浮点转换器

2024-06-17 08:36:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我找到了很多方法在Python中以数字数组的形式输入csv文件,比如thisthis,但是没有一种是我遇到的情况,也没有一种对我有效。我在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]]

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

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

我真的搞不懂这个语法。假设内置转换器可以处理我的数据,那么编写转换器参数的正确语法是什么?如果转换器做不到我需要的,有人知道如何读取这些数据吗?我原以为这会非常简单,我会在5分钟内找到,但我现在已经在这上面浪费了几个小时。


Tags: csv数据方法文档参数np语法情况
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将其转换为float:

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数据框中读取它,可以执行以下操作:

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

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

首先,为了方便起见,我分别创建一个转换公式,并在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)必须分别为每一列指定转换器--我找不到指定“应用于所有列”的方法。更好的方法是使用遍历所有列并将转换应用于所有列的迭代函数…然后该函数将指定哪些列应用于。如果可能的话我不知道怎么做。问题(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的工作原理。这就是说,它似乎不是执行这项任务的一种非常好/可靠的方法,当然,它的文档记录也很差,因此不清楚它能做什么或不能做什么,以及如何获得完成这些任务的方法。

我对未来面临这个问题的人的建议是寻找一种不同的方法来执行这个功能。很多人建议在其他问题中使用pandas来完成类似的任务,但我不知道这样做是否更好。目前,这对我来说是可行的,但在不久的将来,它将不得不被一个更健壮的csv阅读器所取代,以产生一个文件格式,numpy可以很容易地构建成一个数组。

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

相关问题 更多 >