当第一列是字符串,其余的列是数字时,如何使用 numpy.genfortxt?

基本上,我有一组数据,其中第一列是字符串(label) ,其余的列是数值。我运行以下命令:

data = numpy.genfromtxt('data.txt', delimiter = ',')

这可以很好地读取大部分数据,但是 label 列只读取“ nan”。我该怎么办?

123494 次浏览

默认情况下,np.genfromtxt使用 dtype=float: 这就是字符串列被转换为 NaN 的原因,因为它们毕竟不是一个数字..。

你可以让 np.genfromtxt尝试使用 dtype=None来猜测列的实际类型:

>>> from StringIO import StringIO
>>> test = "a,1,2\nb,3,4"
>>> a = np.genfromtxt(StringIO(test), delimiter=",", dtype=None)
>>> print a
array([('a',1,2),('b',3,4)], dtype=[('f0', '|S1'),('f1', '<i8'),('f2', '<i8')])

您可以通过使用列的名称来访问这些列,如 a['f0']..。

如果您不知道您的专栏应该是什么,那么使用 dtype=None是一个很好的技巧。如果您已经知道它们应该具有什么类型,那么可以给出一个显式的 dtype。例如,在我们的测试中,我们知道第一列是一个字符串,第二列是一个整数,我们希望第三列是一个浮点数。然后我们会使用

>>> np.genfromtxt(StringIO(test), delimiter=",", dtype=("|S10", int, float))
array([('a', 1, 2.0), ('b', 3, 4.0)],
dtype=[('f0', '|S10'), ('f1', '<i8'), ('f2', '<f8')])

使用显式 dtype比使用 dtype=None效率更高,是推荐的方法。

在这两种情况下(dtype=None或显式的、非同构的 dtype) ,最终都会得到一个结构化数组。

[注意: 使用 dtype=None,输入会被第二次解析,每个列的类型会被更新以匹配更大的类型: 首先我们尝试一个 bool,然后是一个 int,然后是一个 float,然后是一个 plex,如果其他方法都失败了,我们会保留一个字符串。实际上,这个实现相当笨重。曾经有一些尝试(使用 regexp)提高类型猜测的效率,但是到目前为止还没有成功

如果数据文件的结构如下所示

col1, col2, col3
1,    2,    3
10,   20,   30
100,  200,  300

然后,numpy.genfromtxt可以使用 names=True选项将第一行解释为列标题。通过提供列标题,您可以非常方便地访问数据:

data = np.genfromtxt('data.txt', delimiter=',', names=True)
print data['col1']    # array([   1.,   10.,  100.])
print data['col2']    # array([   2.,   20.,  200.])
print data['col3']    # array([   3.,   30.,  300.])

因为在您的例子中,数据是这样形成的

row1,   1,  10, 100
row2,   2,  20, 200
row3,   3,  30, 300

您可以使用下面的代码片段来实现类似的功能:

labels = np.genfromtxt('data.txt', delimiter=',', usecols=0, dtype=str)
raw_data = np.genfromtxt('data.txt', delimiter=',')[:,1:]
data = {label: row for label, row in zip(labels, raw_data)}

第一行将第一列(标签)读入字符串数组。 第二行从文件中读取所有数据,但是放弃第一列。 第三行使用字典理解来创建一个字典,这个字典可以像 numpy.genfromtxt使用 names=True选项创建的结构化数组一样使用:

print data['row1']    # array([   1.,   10.,  100.])
print data['row2']    # array([   2.,   20.,  200.])
print data['row3']    # array([   3.,   30.,  300.])

您可以使用 numpy.recfromcsv(filename): 每个列的类型将自动确定(就像您使用 np.genfromtxt()dtype=None一样) ,默认情况下是 delimiter=","。这基本上是一个捷径 np.genfromtxt(filename, delimiter=",", dtype=None),皮埃尔通用汽车指出,在他的答案。

对于此格式的数据集:

CONFIG000   1080.65 1080.87 1068.76 1083.52 1084.96 1080.31 1081.75 1079.98
CONFIG001   414.6   421.76  418.93  415.53  415.23  416.12  420.54  415.42
CONFIG010   1091.43 1079.2  1086.61 1086.58 1091.14 1080.58 1076.64 1083.67
CONFIG011   391.31  392.96  391.24  392.21  391.94  392.18  391.96  391.66
CONFIG100   1067.08 1062.1  1061.02 1068.24 1066.74 1052.38 1062.31 1064.28
CONFIG101   371.63  378.36  370.36  371.74  370.67  376.24  378.15  371.56
CONFIG110   1060.88 1072.13 1076.01 1069.52 1069.04 1068.72 1064.79 1066.66
CONFIG111   350.08  350.69  352.1   350.19  352.28  353.46  351.83  350.94

这段代码适用于我的应用程序:

def ShowData(data, names):
i = 0
while i < data.shape[0]:
print(names[i] + ": ")
j = 0
while j < data.shape[1]:
print(data[i][j])
j += 1
print("")
i += 1


def Main():
print("The sample data is: ")
fname = 'ANOVA.csv'
csv = numpy.genfromtxt(fname, dtype=str, delimiter=",")
num_rows = csv.shape[0]
num_cols = csv.shape[1]
names = csv[:,0]
data = numpy.genfromtxt(fname, usecols = range(1,num_cols), delimiter=",")
print(names)
print(str(num_rows) + "x" + str(num_cols))
print(data)
ShowData(data, names)

Python-2输出:

The sample data is:
['CONFIG000' 'CONFIG001' 'CONFIG010' 'CONFIG011' 'CONFIG100' 'CONFIG101'
'CONFIG110' 'CONFIG111']
8x9
[[ 1080.65  1080.87  1068.76  1083.52  1084.96  1080.31  1081.75  1079.98]
[  414.6    421.76   418.93   415.53   415.23   416.12   420.54   415.42]
[ 1091.43  1079.2   1086.61  1086.58  1091.14  1080.58  1076.64  1083.67]
[  391.31   392.96   391.24   392.21   391.94   392.18   391.96   391.66]
[ 1067.08  1062.1   1061.02  1068.24  1066.74  1052.38  1062.31  1064.28]
[  371.63   378.36   370.36   371.74   370.67   376.24   378.15   371.56]
[ 1060.88  1072.13  1076.01  1069.52  1069.04  1068.72  1064.79  1066.66]
[  350.08   350.69   352.1    350.19   352.28   353.46   351.83   350.94]]
CONFIG000:
1080.65
1080.87
1068.76
1083.52
1084.96
1080.31
1081.75
1079.98


CONFIG001:
414.6
421.76
418.93
415.53
415.23
416.12
420.54
415.42


CONFIG010:
1091.43
1079.2
1086.61
1086.58
1091.14
1080.58
1076.64
1083.67


CONFIG011:
391.31
392.96
391.24
392.21
391.94
392.18
391.96
391.66


CONFIG100:
1067.08
1062.1
1061.02
1068.24
1066.74
1052.38
1062.31
1064.28


CONFIG101:
371.63
378.36
370.36
371.74
370.67
376.24
378.15
371.56


CONFIG110:
1060.88
1072.13
1076.01
1069.52
1069.04
1068.72
1064.79
1066.66


CONFIG111:
350.08
350.69
352.1
350.19
352.28
353.46
351.83
350.94

data=np.genfromtxt(csv_file, delimiter=',', dtype='unicode')

我觉得挺好的。

下面是一个从头到尾的示例:

如果我想从没有第一行的文件中导入数字:

 I like trains #this is the first line, a string


1 \t 2 \t 3   #\t is to signify that the delimeter (separation) is tab and not komma


4 \t 5 \t 6

然后运行以下代码:

import numpy as np              #contains genfromtxt
import matplotlib.pyplot as plt #enables plots
from pathlib import Path        # easier using path instead of writing it again and again when you have many files in the same folder
path = r'some_path'             #location of your file in your computer like r'C:my comp\folder\folder2' r is there to make the win 10 path readable in python, it means "just text"
fileNames = [r'\I like trains.txt',
r'\die potato.txt']


data=np.genfromtxt(path + fileNames[0], delimiter='\t', skip_header=1)

产生以下结果:

data = [1 2 3
4 5 6]

每个号码都有自己的单元格,可以单独到达