4

我有一个我经常做的手术,我称之为“锯齿状切片”,因为我不知道它的真实名称。最好通过示例来解释:

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 没有更好的方法。如果需要,您可以为此创建一个辅助函数。

4

3 回答 3

3

我认为您当前的方法可能是最好的方法。

您也可以choose用于这种选择。这在语法上更清晰,但更难以正确处理,并且可能更受限制。这种方法的等价物是:

entries_of_interest.choose(a.T)
于 2015-11-16T13:06:10.637 回答
1

这只是因为它需要更多的打字来完成对您来说似乎如此简单的任务。

a[np.arange(a.shape[0]), entries_of_interest]

但正如您所注意到的,语法上更简单a[:, entries_of_interest]的在numpy. 选择数组列的子集是一项比从每一行中选择一个(随机)项目更常见的任务。

你的案例只是一个特殊的例子

a[I, J]

其中IJ是 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]
于 2015-11-16T17:27:21.683 回答
1

中的元素jagged_slice_of_a是对角线元素a[:,entries_of_interest]

因此,一种稍微不那么繁琐的方法是使用np.diagonal来提取它们。

jagged_slice_of_a = a[:, entries_of_interest].diagonal()
于 2015-11-16T13:05:35.567 回答