我有一个我正常做的操作,我称之为“锯齿状切片”,因为我不知道它的真实名称。最好用例子解释:
a = np.random.randn(50, 10)
entries_of_interest = np.random.randint(10, size = 50) # Vector of 50 indices between 0 and 9
# Now I want the values contained in each row of a at the corresponding index in "entries of interest"
jagged_slice_of_a = a[np.arange(a.shape[0]), entries_of_interest]
# jagged_slice_of_a is now a vector with 50 elements. Good.
唯一的问题是这样做a[np.arange(a.shape[0]), entries_of_interest]
索引有点麻烦(为了这个而必须构造“np.arange(a.shape [0])”似乎很愚蠢)。我想要:
运算符之类的东西,但:
会做其他事情。有没有更简洁的方法来做这个操作?
不,没有更好的方式与原生numpy。如果需要,可以为此创建辅助函数。
答案 0 :(得分:3)
我认为你当前的方法可能是最好的方法。
您也可以使用choose
进行此类选择。这在语法上更清晰,但更难以正确,可能更有限。与此方法等效的是:
entries_of_interest.choose(a.T)
答案 1 :(得分:1)
jagged_slice_of_a
中的元素是a[:,entries_of_interest]
这样做稍微麻烦的方法就是使用np.diagonal
来提取它们。
jagged_slice_of_a = a[:, entries_of_interest].diagonal()
答案 2 :(得分:1)
这仅仅是因为它需要为你看起来很简单的任务进行更多的打字,所以这是精简版。
a[np.arange(a.shape[0]), entries_of_interest]
但是正如您所注意到的,语法更简单的a[:, entries_of_interest]
在numpy
中有另一种解释。选择数组列的子集是一项更常见的任务,即从每行中选择一个(随机)项。
您的案例只是
的专门实例a[I, J]
其中I
和J
是2个相同形状的数组。在一般情况下,entries_of_interest
可能小于a.shape[0]
(不是所有行)或更大(某些行中的几个项目),甚至可能是2d。它甚至可以反复选择某些元素。
我在其他SO问题中发现,当应用于a.flat
时,执行此类元素选择会更快。但这需要一些数学来构造I*n+J
种扁平指数。
凭借您对J
的特殊了解,构建I
似乎是额外的工作,但numpy
无法做出这种假设。如果这种选择更常见,那么有人可以编写一个包装表达式的函数
def peter_selection(a,I):
# check the a.shape[0]==I.shape[0]
return a[np.arange(a.shape[0]), I]