numpy数组中元组索引的奇怪行为

9

当我使用Python 2.7.8和NumPy 1.9.1将一个平坦的NumPy数组与元组列表进行索引时,发现了一些令人困惑的行为。我的猜测是这与数组维度的最大数量有关(我认为是32),但我无法找到文档。

>>> a = np.arange(100)
>>> tuple_index = [(i,) for i in a]
>>> a[tuple_index] # This works (but maybe it shouldn't)
>>> a[tuple_index[:32]] # This works too
>>> a[tuple_index[:31]] # This breaks for 2 <= i < 32
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: too many indices for array
>>> a[tuple_index[:1]] # This also works...

如果元组列表的大小达到32个或更大,是否会对其进行“展平”?这个情况有记录吗?


2
有趣的是,我收到了一个不同的错误信息:IndexError: unsupported iterator index。使用的是Python 2.7和NumPy 1.8.2。 - swenzel
抱歉,我应该指定版本(Python 2.7.8; NumPy 1.9.1)。我已经更新了问题。 - kadrlica
1个回答

6
第一个例子触发了高级索引,它只是在同一维度中选择列表中的索引,而tuple_index[:31]则被视为索引元组,这意味着从多个轴进行选择。
如您所述,NumPy数组的最大维数(通常)为32:
>>> np.MAXDIMS
32

根据mapping.c文件中的以下评论(其中包含解释用户传递的索引的代码),长度小于32的任何元组序列都被扁平化为索引元组:
/*
 * Sequences < NPY_MAXDIMS with any slice objects
 * or newaxis, Ellipsis or other arrays or sequences
 * embedded, are considered equivalent to an indexing
 * tuple. (`a[[[1,2], [3,4]]] == a[[1,2], [3,4]]`)
 */

(我在SciPy网站的官方文档中还没有找到这方面的参考资料。)
这使得a [tuple_index [: 3]]等同于a [(0,), (1,), (2,)],因此出现“太多索引”错误(因为a只有一个维度,但我们暗示有三个维度)。
另一方面,a [tuple_index]a [[(0,), (1,), (2,),...,(99,)]]相同,结果是2D数组。

基础文档声称索引数组必须是整数类型。显然,实现仍然允许这样做。我仍然无法弄清楚的是,为什么从元组列表中获得大于np.MAXDIMS的2D数组。 - Eric Appelt
我同意这似乎不是很明显(我不知道是否有意)。当长度大于MAXDIMS时,它看起来像是将元组列表[(0,), (1,), (2,) ..., (99,)]内部转换为NumPy数组(它将变成一个2D数组)。然后使用它来索引原始的1D数组(返回一个2D数组)。 - Alex Riley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接