numpy 索引:尾随省略号不应该是多余的吗?
numpy indexing: shouldn't trailing Ellipsis be redundant?
在尝试正确理解 numpy 索引规则时,我偶然发现了以下内容。我曾经认为索引中的尾随省略号没有任何作用。微不足道不是吗?除了,它实际上不是真的:
Python 3.5.2 (default, Nov 11 2016, 04:18:53)
[GCC 4.8.5] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>>
>>> D2 = np.arange(4).reshape((2, 2))
>>>
>>> D2[[1, 0]].shape; D2[[1, 0], ...].shape
(2, 2)
(2, 2)
>>> D2[:, [1, 0]].shape; D2[:, [1, 0], ...].shape
(2, 2)
(2, 2)
>>> # so far so expected; now
...
>>> D2[[[1, 0]]].shape; D2[[[1, 0]], ...].shape
(2, 2)
(1, 2, 2)
>>> # ouch!
...
>>> D2[:, [[1, 0]]].shape; D2[:, [[1, 0]], ...].shape
(2, 1, 2)
(2, 1, 2)
现在有人可以告诉我这是错误还是功能?
如果是后者,理由是什么?
提前致谢,
保罗
显然对 [[1, 0]]
索引的解释存在一些歧义。可能在这里讨论了同样的事情:
我会尝试一个不同的数组,看看它是否能让事情变得清晰
In [312]: D2=np.array([[0,0],[1,1],[2,2]])
In [313]: D2
Out[313]:
array([[0, 0],
[1, 1],
[2, 2]])
In [316]: D2[[[1,0,0]]]
Out[316]:
array([[1, 1],
[0, 0],
[0, 0]])
In [317]: _.shape
Out[317]: (3, 2)
使用:
或...
或将索引列表做成数组,都将其视为(1,3)索引,并相应扩展结果的维度
In [318]: D2[[[1,0,0]],:]
Out[318]:
array([[[1, 1],
[0, 0],
[0, 0]]])
In [319]: _.shape
Out[319]: (1, 3, 2)
In [320]: D2[np.array([[1,0,0]])]
Out[320]:
array([[[1, 1],
[0, 0],
[0, 0]]])
In [321]: _.shape
Out[321]: (1, 3, 2)
请注意,如果我将转置应用于索引数组,我会得到 (3,1,2) 结果
In [323]: D2[np.array([[1,0,0]]).T,:]
...
In [324]: _.shape
Out[324]: (3, 1, 2)
没有 :
或 ...
,它似乎在将 []
应用到第一个轴之前剥离了一层:
In [330]: D2[[1,0,0]].shape
Out[330]: (3, 2)
In [331]: D2[[[1,0,0]]].shape
Out[331]: (3, 2)
In [333]: D2[[[[1,0,0]]]].shape
Out[333]: (1, 3, 2)
In [334]: D2[[[[[1,0,0]]]]].shape
Out[334]: (1, 1, 3, 2)
In [335]: D2[np.array([[[[1,0,0]]]])].shape
Out[335]: (1, 1, 1, 3, 2)
我认为这里存在向后兼容性问题。我们知道元组层是'redundant':D2[(1,2)]
和D2[1,2]
是一样的。但是为了与 numpy
(numeric
) 的早期版本兼容,第一个 []
层可能会以相同的方式处理。
在 11 月的那个问题中,我注意到:
So at a top level a list and tuple are treated the same - if the list can't interpreted as an advanced indexing list.
添加 ...
是将 D2[[[0,1]]]
与 D2[([0,1],)]
分开的另一种方式。
来自 @eric/s
拉取请求 seburg
解释
The tuple normalization is a rather small thing (it basically checks for a non-array sequence of length <= np.MAXDIMS, and if it contains another sequence, slice or None consider it a tuple).
[[1,2]]
是1个元素的列表,有一个列表,所以它被认为是一个元组,即([1,2],)
。 [[1,2]],...
已经是元组了。
在尝试正确理解 numpy 索引规则时,我偶然发现了以下内容。我曾经认为索引中的尾随省略号没有任何作用。微不足道不是吗?除了,它实际上不是真的:
Python 3.5.2 (default, Nov 11 2016, 04:18:53)
[GCC 4.8.5] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>>
>>> D2 = np.arange(4).reshape((2, 2))
>>>
>>> D2[[1, 0]].shape; D2[[1, 0], ...].shape
(2, 2)
(2, 2)
>>> D2[:, [1, 0]].shape; D2[:, [1, 0], ...].shape
(2, 2)
(2, 2)
>>> # so far so expected; now
...
>>> D2[[[1, 0]]].shape; D2[[[1, 0]], ...].shape
(2, 2)
(1, 2, 2)
>>> # ouch!
...
>>> D2[:, [[1, 0]]].shape; D2[:, [[1, 0]], ...].shape
(2, 1, 2)
(2, 1, 2)
现在有人可以告诉我这是错误还是功能? 如果是后者,理由是什么?
提前致谢, 保罗
显然对 [[1, 0]]
索引的解释存在一些歧义。可能在这里讨论了同样的事情:
我会尝试一个不同的数组,看看它是否能让事情变得清晰
In [312]: D2=np.array([[0,0],[1,1],[2,2]])
In [313]: D2
Out[313]:
array([[0, 0],
[1, 1],
[2, 2]])
In [316]: D2[[[1,0,0]]]
Out[316]:
array([[1, 1],
[0, 0],
[0, 0]])
In [317]: _.shape
Out[317]: (3, 2)
使用:
或...
或将索引列表做成数组,都将其视为(1,3)索引,并相应扩展结果的维度
In [318]: D2[[[1,0,0]],:]
Out[318]:
array([[[1, 1],
[0, 0],
[0, 0]]])
In [319]: _.shape
Out[319]: (1, 3, 2)
In [320]: D2[np.array([[1,0,0]])]
Out[320]:
array([[[1, 1],
[0, 0],
[0, 0]]])
In [321]: _.shape
Out[321]: (1, 3, 2)
请注意,如果我将转置应用于索引数组,我会得到 (3,1,2) 结果
In [323]: D2[np.array([[1,0,0]]).T,:]
...
In [324]: _.shape
Out[324]: (3, 1, 2)
没有 :
或 ...
,它似乎在将 []
应用到第一个轴之前剥离了一层:
In [330]: D2[[1,0,0]].shape
Out[330]: (3, 2)
In [331]: D2[[[1,0,0]]].shape
Out[331]: (3, 2)
In [333]: D2[[[[1,0,0]]]].shape
Out[333]: (1, 3, 2)
In [334]: D2[[[[[1,0,0]]]]].shape
Out[334]: (1, 1, 3, 2)
In [335]: D2[np.array([[[[1,0,0]]]])].shape
Out[335]: (1, 1, 1, 3, 2)
我认为这里存在向后兼容性问题。我们知道元组层是'redundant':D2[(1,2)]
和D2[1,2]
是一样的。但是为了与 numpy
(numeric
) 的早期版本兼容,第一个 []
层可能会以相同的方式处理。
在 11 月的那个问题中,我注意到:
So at a top level a list and tuple are treated the same - if the list can't interpreted as an advanced indexing list.
添加 ...
是将 D2[[[0,1]]]
与 D2[([0,1],)]
分开的另一种方式。
来自 @eric/s
拉取请求 seburg
解释
The tuple normalization is a rather small thing (it basically checks for a non-array sequence of length <= np.MAXDIMS, and if it contains another sequence, slice or None consider it a tuple).
[[1,2]]
是1个元素的列表,有一个列表,所以它被认为是一个元组,即([1,2],)
。 [[1,2]],...
已经是元组了。