索引n维数组与(n-1)d数组

200*_*ach 13 python numpy

使用沿给定维度的(n-1)维数组访问n维数组的最优雅方法是什么,如虚拟示例中所示

a = np.random.random_sample((3,4,4))
b = np.random.random_sample((3,4,4))
idx = np.argmax(a, axis=0)
Run Code Online (Sandbox Code Playgroud)

我现在如何访问idx a以获得最大值,a就像我使用过一样a.max(axis=0)?或者如何检索idxin中指定的值b

我想过使用,np.meshgrid但我认为这是一种矫枉过正.请注意,尺寸axis可以是任何有用的轴(0,1,2),并且事先不知道.有一种优雅的方式来做到这一点?

Div*_*kar 11

利用advanced-indexing-

m,n = a.shape[1:]
I,J = np.ogrid[:m,:n]
a_max_values = a[idx, I, J]
b_max_values = b[idx, I, J]
Run Code Online (Sandbox Code Playgroud)

对于一般情况:

def argmax_to_max(arr, argmax, axis):
    """argmax_to_max(arr, arr.argmax(axis), axis) == arr.max(axis)"""
    new_shape = list(arr.shape)
    del new_shape[axis]

    grid = np.ogrid[tuple(map(slice, new_shape))]
    grid.insert(axis, argmax)

    return arr[tuple(grid)]
Run Code Online (Sandbox Code Playgroud)

不幸的是,应该比这种自然操作更加尴尬.

为了使用n dim数组索引(n-1) dim数组,我们可以简化一下,为我们提供所有轴的索引网格,如下所示 -

def all_idx(idx, axis):
    grid = np.ogrid[tuple(map(slice, idx.shape))]
    grid.insert(axis, idx)
    return tuple(grid)
Run Code Online (Sandbox Code Playgroud)

因此,使用它来索引输入数组 -

axis = 0
a_max_values = a[all_idx(idx, axis=axis)]
b_max_values = b[all_idx(idx, axis=axis)]
Run Code Online (Sandbox Code Playgroud)

  • all_idx非常优雅。喜欢你的帖子,@ Divakar! (2认同)
  • @unutbu啊我现在看到了!因此,如果输入`a`是一维数组,那么使用元组,我们将得到一个标量,它复制`.max()`行为.但是如果没有元组,我们会得到一个带有一个元素的数组.所以,也许这是将其视为元组的一个原因. (2认同)
  • `all_idx`很好.我没有意识到使用argmax输出的形状而不是原始数组的形状会简化事情.至于元组而不是列表,高级索引语义更清晰,具有元组.在这种情况下,列表的行为恰好相同,因为在某些条件下将列表转换为元组的向后兼容性处理(不完全正确记录).将列表视为元组并且在NumPy索引中将列表视为数组时,可能会令人惊讶,因此我更喜欢显式创建元组. (2认同)
  • 作为参考,我所指的向后兼容性处理是[这里](https://github.com/numpy/numpy/blob/7ccf0e08917d27bc0eba34013c1822b00a66ca6d/numpy/core/src/multiarray/mapping.c#L200).`idx`是标量的情况是我甚至没有考虑过的,其中不会触发向后兼容性处理,如果我们保留列表而不是元组,则会出现错误的结果.如此所示,元组的行为更加一致且更容易预测. (2认同)
  • 已添加`take_along_axis` 以使这更容易。还有一个`put` (2认同)