与花哨的索引混淆(对于非花哨的人)
Confusion with Fancy indexing (for non-fancy people)
让我们假设一个多维数组
import numpy as np
foo = np.random.rand(102,43,35,51)
我知道那些最后的维度代表一个 2D space (35,51),我想索引 的一系列行 =]列
假设我想要第 0 列的第 8 行到第 30 行
根据我对索引的理解,我应该调用
foo[0][0][8::30][0]
尽管知道我的数据(与此处使用的随机数据不同),但这不是我所期望的
我可以试试这个确实有效但看起来很荒谬
foo[0][0][[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],0]
现在我可以在 this documentation 中找到我也可以使用
类似于:
foo[0][0][[8,30],0]
这只给我第 8 行和第 30 行的值
而这个:
foo[0][0][[8::30],0]
报错
File "<ipython-input-568-cc49fe1424d1>", line 1
foo[0][0][[8::30],0]
^
SyntaxError: invalid syntax
我不明白为什么不能在这里传递::参数。那么在索引语法中指示范围的方法是什么?
所以我想我的总体问题是这种语法的正确 pythonic 等价物是什么:
foo[0][0][[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],0]
而不是
foo[0][0][8::30][0]
尝试
foo[0, 0, 8:30, 0]
foo[0][0]
部分与 foo[0, 0, :, :]
相同,选择二维数组 (35 x 51)。但是 foo[0][0][8::30]
选择了这些行的子集
考虑在二维数组上使用 0::30
时会发生什么:
In [490]: np.zeros((35,51))[0::30].shape
Out[490]: (2, 51)
In [491]: np.arange(35)[0::30]
Out[491]: array([ 0, 30])
30
是切片的 step
,而不是 stop
值。
最后一个 [0]
然后选择这些行中的第一行。最终结果与 foo[0,0,0,:]
.
相同
在大多数情况下,使用逗号语法索引多个维度会更好。如果您想要前 30 行,请使用 0:30
,而不是 0::30
(这是基本的切片符号,适用于列表和数组)。
至于:
foo[0][0][[8::30],0]
简化为x[[8::30], 0]
。 Python 解释器接受 [1:2:3, 0]
,将其翻译成 tuple(slice(1,2,3), 0)
并将其传递给 __getitem__
方法。但是冒号语法在非常特定的上下文中被接受。解释器将内部括号组视为一个列表,那里不接受冒号。
foo[0,0,[1,2,3],0]
没问题,因为内括号是一个列表,而 numpy getitem
可以处理这些。
numpy
有一个工具可以将切片表示法转换为数字列表。如果它仍然令人困惑,请尝试一下:
In [495]: np.r_[8:30]
Out[495]:
array([ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29])
In [496]: np.r_[8::30]
Out[496]: array([0])
In [497]: np.r_[8:30:2]
Out[497]: array([ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28])
让我们假设一个多维数组
import numpy as np
foo = np.random.rand(102,43,35,51)
我知道那些最后的维度代表一个 2D space (35,51),我想索引 的一系列行 =]列 假设我想要第 0 列的第 8 行到第 30 行 根据我对索引的理解,我应该调用
foo[0][0][8::30][0]
尽管知道我的数据(与此处使用的随机数据不同),但这不是我所期望的
我可以试试这个确实有效但看起来很荒谬
foo[0][0][[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],0]
现在我可以在 this documentation 中找到我也可以使用 类似于:
foo[0][0][[8,30],0]
这只给我第 8 行和第 30 行的值 而这个:
foo[0][0][[8::30],0]
报错
File "<ipython-input-568-cc49fe1424d1>", line 1
foo[0][0][[8::30],0]
^
SyntaxError: invalid syntax
我不明白为什么不能在这里传递::参数。那么在索引语法中指示范围的方法是什么?
所以我想我的总体问题是这种语法的正确 pythonic 等价物是什么:
foo[0][0][[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],0]
而不是
foo[0][0][8::30][0]
尝试
foo[0, 0, 8:30, 0]
foo[0][0]
部分与 foo[0, 0, :, :]
相同,选择二维数组 (35 x 51)。但是 foo[0][0][8::30]
选择了这些行的子集
考虑在二维数组上使用 0::30
时会发生什么:
In [490]: np.zeros((35,51))[0::30].shape
Out[490]: (2, 51)
In [491]: np.arange(35)[0::30]
Out[491]: array([ 0, 30])
30
是切片的 step
,而不是 stop
值。
最后一个 [0]
然后选择这些行中的第一行。最终结果与 foo[0,0,0,:]
.
在大多数情况下,使用逗号语法索引多个维度会更好。如果您想要前 30 行,请使用 0:30
,而不是 0::30
(这是基本的切片符号,适用于列表和数组)。
至于:
foo[0][0][[8::30],0]
简化为x[[8::30], 0]
。 Python 解释器接受 [1:2:3, 0]
,将其翻译成 tuple(slice(1,2,3), 0)
并将其传递给 __getitem__
方法。但是冒号语法在非常特定的上下文中被接受。解释器将内部括号组视为一个列表,那里不接受冒号。
foo[0,0,[1,2,3],0]
没问题,因为内括号是一个列表,而 numpy getitem
可以处理这些。
numpy
有一个工具可以将切片表示法转换为数字列表。如果它仍然令人困惑,请尝试一下:
In [495]: np.r_[8:30]
Out[495]:
array([ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29])
In [496]: np.r_[8::30]
Out[496]: array([0])
In [497]: np.r_[8:30:2]
Out[497]: array([ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28])