如何正确定义numpy dtype

时间:2017-01-12 18:11:32

标签: numpy

我有这样的代码,我尝试从csv文件

加载四列
import numpy as np
rtype = np.dtype([('1', np.float), ('2', np.float), ('3', np.float), ('tier', np.str, 32)])
x1, x2, x3, x4 = np.genfromtxt("../Data/out.txt", dtype=rtype, skip_header=1, delimiter=",", usecols=(3, 4, 5, 6), unpack=True)

但我有一个错误:

ValueError: too many values to unpack (expected 4)

这有点奇怪,因为我有四个变量并加载了四列。

如何正确加载它们? 恕我直言,问题在np.dtype,因为没有它,一切正常(尽管有其他类型)。我使用python3。

1 个答案:

答案 0 :(得分:2)

看起来你的文字如下:

In [447]: txt=b"""1.2 3.3 2.0 str
     ...: 3.3 3.3 2.2 astring
     ...: """

我的第一个选择是genfromtxt dtype=None(自动dtype确定):

In [448]: np.genfromtxt(txt.splitlines(),dtype=None)
Out[448]: 
array([(1.2, 3.3, 2.0, b'str'), (3.3, 3.3, 2.2, b'astring')], 
      dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8'), ('f3', 'S7')])

没有dtype它会尝试使所有东西都浮动 - 包括字符串列:

In [449]: np.genfromtxt(txt.splitlines())
Out[449]: 
array([[ 1.2,  3.3,  2. ,  nan],
       [ 3.3,  3.3,  2.2,  nan]])

我不使用unpack,更喜欢获得一个2d或结构化数组。但是打开包装:

In [450]: x1,x2,x3,x4=np.genfromtxt(txt.splitlines(),unpack=True)
In [451]: x1
Out[451]: array([ 1.2,  3.3])
In [452]: x4
Out[452]: array([ nan,  nan])

我仍然获得字符串列的nan

借用dtype=None案例中的dtype:

In [456]: dt=np.dtype([('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8'), ('f3', 'S7')])
In [457]: dt
Out[457]: dtype([('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8'), ('f3', 'S7')])
In [458]: np.genfromtxt(txt.splitlines(),unpack=True,dtype=dt)
Out[458]: 
array([(1.2, 3.3, 2.0, b'str'), (3.3, 3.3, 2.2, b'astring')], 
      dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8'), ('f3', 'S7')])
In [459]: _.shape
Out[459]: (2,)

使用此复合dtype,unpack每行给出一个项目,而不是每列一个项目。换句话说,unpack不会拆分结构化字段。

处理字符串列并仍使用解压缩的一种方法是读取文本两次:

首先加载浮动列:

In [462]: x1,x2,x3=np.genfromtxt(txt.splitlines(),unpack=True,usecols=[0,1,2])
In [463]: x3
Out[463]: array([ 2. ,  2.2])

然后使用dtype=NoneS32加载字符串列:

In [466]: x4=np.genfromtxt(txt.splitlines(),unpack=True,usecols=[3],dtype=None)
In [467]: x4
Out[467]: 
array([b'str', b'astring'], 
      dtype='|S7')

另一种选择是加载结构化数组,并单独解压缩字段

In [468]: data = np.genfromtxt(txt.splitlines(),dtype=None)
In [469]: data.dtype
Out[469]: dtype([('f0', '<f8'), ('f1', '<f8'), ('f2', '<f8'), ('f3', 'S7')])
In [470]: x1, x2, x3 = data['f0'],data['f1'],data['f2']
In [471]: x4 = data['f3']
In [472]: x4
Out[472]: 
array([b'str', b'astring'], 
      dtype='|S7')

使用genfromtxt最安全的方法是

data = np.genfromtxt(...)
print(data.shape)
print(data.dtype)

然后确保在继续使用data数组之前了解该形状和dtype。