genfromtxt生成元组,recfromcsv也是如此
我有一个CSV文件(用逗号分隔),结构如下:
A1,A2,A3
16516.1556163,163163.48315,41816.844334
当我尝试用numpy把它变成一个二维矩阵时,它总是被转换成一种结构化数组。根据这个CSV文件的结构,我使用了:
y = np.genfromtxt('file.csv', delimiter=',', usecols=(0,2), names=True)
或者
y = np.recfromcsv('file.csv', usecols=(0,2)
在这两种情况下,我的数组形状都是(1,),而不是(1,2)。查看genfromtxt或recfromcsv生成的数据类型,我发现它们的类型都是一样的('a1', '<f8')。
你能告诉我如何从CSV文件读取数据并把数组格式调整正确吗?
谢谢,托马斯
3 个回答
我花了一些时间考虑了两个建议,因为我已经尝试了第一个建议里的基本所有方法,所以我决定使用astropy。我在文档中看到它支持csv格式,但老实说,我在0.3版本时从来没成功过。0.3.2版本支持的格式里没有csv,而在PyPi上,这就是最新的版本。
不过,我试了试format='fixed_width'
,虽然有东西被读取进来了,但数值却完全搞错了。
我还是搞不懂,但当我用skip_header=1
跳过第一行,并且完全不设置names
(默认是None
)的时候,它就能正常工作了。
现在,当我说:
x = np.genfromtxt('file.csv', delimiter=',', skip_header=1)
x.shape
结果是(10615, 52)
你可以使用 astropy
库来读取你的 csv
文件,这个库可以处理表格数据。下面是一个简单的示例:
>>> from astropy.io import ascii
>>> from numpy import *
>>> data = ascii.read("test.csv",format='csv',delimiter=',')
>>> print data
A1 A2 A3
------------- ------------ ------------
16516.1556163 163163.48315 41816.844334
然后,你可以用 numpy
将它转换成一个有三列的数组。顺便提一下,你不能把字符串和浮点数放在同一个数组里。
>>> a = hstack((data['A1'],data['A2'],data['A3']))
>>> print a
[ 16516.1556163 163163.48315 41816.844334 ]
当我尝试运行你的代码时,我得到了:
In [71]: c = StringIO("A1,A2,A3\n16516.1556163,163163.48315,41816.844334")
In [72]: x = np.genfromtxt(c,delimiter=',',usecols=(0,2),names=True)
Out[72]:
array((16516.1556163, 41816.844334),
dtype=[('A1', '<f8'), ('A3', '<f8')])
In [73]: x.shape
Out[73]: ()
In [83]: x.item()
Out[83]: (16516.1556163, 41816.844334)
In [129]: x.reshape((1,))
Out[129]:
array([(16516.1556163, 41816.844334)],
dtype=[('A1', '<f8'), ('A3', '<f8')])
所以,x
是一个记录数组。只有一行数据时,它的形状是 ()
(也就是“标量”)。如果你给它两行数据,形状就会变成 (2,)
。如果设置了 'names=False',并且你让它跳过第一行,那么结果(有两行数据时)会是 (2,2)
。
这些 '...fromtxt' 函数会逐行读取文件,解析每一行,然后构建一个列表的列表,比如 [[1,2,3],[3,4,5]]
。接着,这个列表会传给 np.array
(并指定合适的数据类型 dtype
)。最后,它会经过 .squeeze()
,去掉所有单一维度。
正是这个最后的 squeeze
把形状为 (1,)
的数组变成了 ()
(或者 (1,2)->(2,)
)。你可以很容易地用 reshape
把这个维度加回来。
要创建一个有两列的矩阵,你需要跳过表头和名称:
In [121]: x=np.genfromtxt(c,delimiter=',',usecols=(0,2),skip_header=1)
In [122]: x
Out[122]: array([ 16516.1556163, 41816.844334 ])
In [123]: x.shape
Out[123]: (2,)