genfromtxt生成元组,recfromcsv也是如此

0 投票
3 回答
582 浏览
提问于 2025-04-18 11:10

我有一个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 个回答

0

我花了一些时间考虑了两个建议,因为我已经尝试了第一个建议里的基本所有方法,所以我决定使用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)

0

你可以使用 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 ]
1

当我尝试运行你的代码时,我得到了:

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,)

撰写回答