Python 结构化数组的索引和切片

Python 结构化数组的索引和切片,python,arrays,numpy,indexing,record,Python,Arrays,Numpy,Indexing,Record,现在我正试图理解索引numpy结构化数组的可能方法,我有点被它卡住了。以下是几个简单的例子: import numpy as np arr = np.array(zip(range(5), range(5, 10)), dtype=[('a', int), ('b', int)]) arr[0] # first row (record) arr[(0,)] # the same, as expected arr['a'] # field 'a' of each record arr[('a'

现在我正试图理解索引
numpy
结构化数组的可能方法,我有点被它卡住了。以下是几个简单的例子:

import numpy as np
arr = np.array(zip(range(5), range(5, 10)), dtype=[('a', int), ('b', int)])

arr[0] # first row (record)
arr[(0,)] # the same, as expected

arr['a'] # field 'a' of each record
arr[('a',)] # "IndexError: unsupported iterator index" ?!

arr[1:3] # second and third rows (records)
arr[1:3, 'a'] # "ValueError: invalid literal for long() with base 10: 'a'" ?!
arr['a', 1:3] # same error
arr[..., 'a'] # here too...
arr['a', ...] # and here
因此,出现了两个子问题:

  • 为什么普通值(
    'a'
    在本例中)的结果不同于相应的单例
    元组(
    ('a',)
  • 为什么最后四行会引起错误?而且,可能更重要的是,如何用单个切片获得切片
    arr['a'][1:3]
    ?如您所见,显而易见的
    arr['a',1:3]
    不起作用

我还观察了内置
列表
和非结构化
ndarray
的索引行为,但没有发现这样的问题:在元组中放入一个值不会改变任何事情,当然,对于普通
ndarray
来说,像
arr[1,1:3]
这样的索引也能按预期工作。考虑到这一点,我的示例中的错误是否应该被视为
numpy
中的bug?

首先,字段与维度不是一回事-尽管数组
arr
有两个字段和五行,但numpy实际上将其视为一维(它具有形状
(5,)
)。其次,元组在用作numpy数组的索引时具有特殊的状态。当您将元组放在索引方括号内时,numpy将其解释为数组相应维度的索引序列。在嵌套元组的特殊情况下,每个内部元组都被视为该维度的一系列索引(就好像它是一个
列表

由于字段不算作维度,当您使用
arr[('a',)]
对其进行索引时,numpy将
'a'
解释为对
arr
行的索引。因此会引发
索引器错误
,因为字符串不是索引到数组维度的有效类型(“a”行是什么?)

当您尝试
arr['a',1:3]
时也会发生同样的情况,因为这相当于使用元组
('a',slice(1,3,None))
进行索引。
'a'
1:3
之间的逗号使其成为元组,而不管是否缺少括号。同样,numpy尝试使用
'a'
索引到
arr
的行中,这是无效的。但是,即使这两个元素都是有效的索引类型,您仍然会得到一个
索引器
,因为元组(2)的长度大于
arr
(1)中的维度数


arr['a'][1:3]
arr[1:3]['a']
都是索引字段切片的非常有效的方法。

我想,如果字段是类型和字节长度的混合体,您可以在这样的数组上发布功能请求。在您的情况下,字段都是相同的类型,也可以用普通的
ndarray
表示。该结构增加的全部功能是使用名称“索引”值。字典
{'A':0,'b':1}
或变量赋值
A,b=0,1
也应该可以。是的,实际上它回答了这个问题,同时也破坏了我对一致行为的希望(我希望我错过了一些东西)。。。这对于用户来说是非常不直观的,因为在标准库和numpy中,传递一个单元组作为索引而不是一个普通值会完全改变结果(第二个问题也是由这个事实引起的)。我可能会为numpy发布一个特性请求,但这也可能被认为是一个bug——因为行为完全不一致。为什么不把字段当作一个额外的维度,或者在这种情况下允许它们……您是在要求从根本上改变数组数据的存储和访问方式,还是仅仅在符号上做一个表面的改变?您是否会更改维度上的操作,如
重塑
交换盘
?我认为这将是一个可怕的混乱-您需要将字段设置为一个“特殊”维度,这需要一种完全不同的语法来进行索引(
arr['foo':'bar']
显然没有意义)。如果字段包含异构数据类型,则会完全破坏
.restrape()
.ravel()
等。
arr['a'][1:3]
通常更可取。@seberg有什么特殊原因吗?我没有注意到这两种方法在索引性能上有太大的差异,即使对于一个包含1000个随机
float64
字段的
(10000,)
数组也是如此。