按名称和索引的Numpy结构化数组

时间:2016-02-07 22:00:16

标签: python arrays numpy

我似乎无法让NumPy数组为我工作得很好。 :(

我的数据集很简单:150行4个浮点数后跟一个字符串。我尝试了以下方法:

data = np.genfromtxt("iris.data2", delimiter=",", names=["SL", "SW", "PL", "PW", "class"], dtype=[float, float, float, float, '|S16'])

print(data.shape) ---> (150, 0)
print(data["PL"])
print(data[:, 0:3]) <---error

所以我通过简单的文件替换将它改为5个浮点数。我只这样做是因为我无法使非同类数组与列名和索引访问一起很好地工作。但是现在我已经把它变成了同质的,它仍然给了我一个(150,0)的形状和错误。

data = np.genfromtxt("iris.data", delimiter=",", names=["SL", "SW", "PL", "PW", "class"])

print(data.shape) ---> (150, 0)
print(data["PL"])
print(data[:, 0:3]) <--- error

当我完全删除名称时,它适用于索引列访问,但显然不再是名称。

data = np.genfromtxt("iris.data", delimiter=",")

print(data.shape) ---> (150, 5)
# print(data["PL"])
print(data[:, 0:3]) ---> WORKS GREAT!!!

为什么会这样,我该如何解决?理想情况下,我希望名称和索引列访问,而不用浮点代码替换字符串,但如果我需要获取名称和索引列访问权限,我会这样做。

2 个答案:

答案 0 :(得分:2)

1d结构化数组的字段和2d数组的列之间有明显的区别。它们不可互换。字段名称不仅仅是列标签。如果不清楚,您需要更详细地阅读dtypestructured array文档。

定义伪文件:

In [93]: txt=b"""1,2,3,4,txt
   ....: 5,6,7,8,abc"""

In [94]: np.genfromtxt(txt.splitlines(),delimiter=',',dtype=None)
Out[94]: 
array([(1, 2, 3, 4, 'txt'), (5, 6, 7, 8, 'abc')], 
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4'), ('f4', 'S3')])

对于混合列,加载它的默认方式是结构化数组,包含2行(shape =(2,))和5个字段,索引为data['f0']data[['f0','f2']]。一次索引多个字段的能力有限。

但我们可以定义一个复合dtype,例如:

In [102]: dt=np.dtype([('data',float,(4,)),('lbl','|S5')])

In [103]: dt
Out[103]: dtype([('data', '<f8', (4,)), ('lbl', 'S5')])

In [104]: np.genfromtxt(txt.splitlines(),delimiter=',',dtype=dt)
Out[104]: 
array([([1.0, 2.0, 3.0, 4.0], 'txt'), ([5.0, 6.0, 7.0, 8.0], 'abc')], 
      dtype=[('data', '<f8', (4,)), ('lbl', 'S5')])

In [105]: data=np.genfromtxt(txt.splitlines(),delimiter=',',dtype=dt)

In [106]: data['data']
Out[106]: 
array([[ 1.,  2.,  3.,  4.],
       [ 5.,  6.,  7.,  8.]])

In [107]: data['lbl']
Out[107]: 
array(['txt', 'abc'], 
      dtype='|S5')

In [108]: data[0]
Out[108]: ([1.0, 2.0, 3.0, 4.0], 'txt')

现在data['data']是一个二维数组,包含原始文本中的数值。

字段名称可以作为元组获取:

In [112]: data.dtype.names
Out[112]: ('data', 'lbl')

因此可以对它们执行常规的列表/元组索引,甚至可以通过以相反的顺序查看字段来进行复杂的处理:

In [115]: data[list(data.dtype.names[::-1])]
Out[115]: 
array([('txt', [1.0, 2.0, 3.0, 4.0]), ('abc', [5.0, 6.0, 7.0, 8.0])], 
      dtype=[('lbl', 'S5'), ('data', '<f8', (4,))])

答案 1 :(得分:1)

一旦你将一个序列或一串逗号分隔的名称传递给 names 参数,那么你得到的数据就是一个一维数组。这就是 data[:, 0:3] 不起作用的原因

In[95]: data = np.genfromtxt("datasets\iris.csv", delimiter=",", \
                     names=["SL", "SW", "PL", "PW", "class"], \
                     dtype=[float, float, float, float, '|S16'])
data.shape
Out[95]: (151,)

In[96]: data = np.genfromtxt("datasets\iris.csv", delimiter=",")
data.shape
Out[96]: (151, 6)