简体   繁体   English

基于2d掩模数组的numpy 3d到2d变换

[英]numpy 3d to 2d transformation based on 2d mask array

If I have an ndarray like this: 如果我有这样的ndarray:

>>> a = np.arange(27).reshape(3,3,3)
>>> a
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]],

       [[18, 19, 20],
        [21, 22, 23],
        [24, 25, 26]]])

I know I can get the maximum along a certain axis using np.max(axis=...) : 我知道我可以使用np.max(axis=...)沿某个轴获得最大值:

>>> a.max(axis=2)
array([[ 2,  5,  8],
       [11, 14, 17],
       [20, 23, 26]])

Alternatively, I could get the indices along that axis which correspond to the maximum values from: 或者,我可以获得沿该轴的索引 ,这些索引对应于以下的最大值:

>>> indices = a.argmax(axis=2)
>>> indices
array([[2, 2, 2],
       [2, 2, 2],
       [2, 2, 2]])

My question -- Given the array indices and the array a , is there an elegant way to reproduce the array the array returned by a.max(axis=2) ? 我的问题 - 给定数组indices和数组a ,是否有一种优雅的方法来重现a.max(axis=2)返回的数组?

This would probably work: 这可能会奏效:

import itertools as it
import numpy as np
def apply_mask(field,indices):
    data = np.empty(indices.shape)

    #It seems highly likely that there is a more numpy-approved way to do this.
    idx = [range(i) for i in indices.shape]
    for idx_tup,zidx in zip(it.product(*idx),indices.flat):
        data[idx_tup] = field[idx_tup+(zidx,)]
    return data

But, it seems pretty hacky/inefficient. 但是,它似乎非常hacky /低效。 It also doesn't allow for me to use this with any axis other than the "last" axis. 它也不允许我使用除“最后”轴以外的任何轴。 Is there a numpy function (or some use of magical numpy indexing) to make this work? 是否有一个numpy函数(或一些使用神奇的numpy索引)来使这项工作? The naive a[:,:,a.argmax(axis=2)] doesn't work. 天真的a[:,:,a.argmax(axis=2)]不起作用。

UPDATE : 更新

It seems the following also works (and is a little nicer): 似乎以下也有效(并且更好一些):

import numpy as np
def apply_mask(field,indices):
    data = np.empty(indices.shape)

    for idx_tup,zidx in np.ndenumerate(indices):
        data[idx_tup] = field[idx_tup+(zidx,)]

    return data

I would like to do this because I would like to extract the indices based on the data in 1 array (typically using argmax(axis=...) ) and use those indices to pull data out of a bunch of other (equivalently shaped) arrays. 我想这样做是因为我想基于1个数组中的数据提取索引(通常使用argmax(axis=...) )并使用这些索引从一堆其他数据中提取数据(等效形状)阵列。 I'm open to alternative ways to accomplish this (eg using boolean masked arrays). 我愿意采用其他方法来实现这一目标(例如使用布尔掩码数组)。 However, I like the "safety" that I get using these "index" arrays. 但是,我喜欢使用这些“索引”数组的“安全性”。 With this I am guaranteed to have the right number of elements to create a new array which looks like a 2d "slice" through the 3d field. 有了这个,我保证有适当数量的元素来创建一个新的数组,看起来像是通过3d字段的2d“切片”。

Here is some magic numpy indexing that will do what you want, but unfortunately it's pretty unreadable. 这里有一些神奇的numpy索引可以做你想要的,但不幸的是它很难读。

def apply_mask(a, indices, axis):
    magic_index = [np.arange(i) for i in indices.shape]
    magic_index = np.ix_(*magic_index)
    magic_index = magic_index[:axis] + (indices,) + magic_index[axis:]
    return a[magic_index]

or equally unreadable: 或同样不可读:

def apply_mask(a, indices, axis):
    magic_index = np.ogrid[tuple(slice(i) for i in indices.shape)]
    magic_index.insert(axis, indices)
    return a[magic_index]

I use index_at() to create the full index: 我使用index_at()来创建完整索引:

import numpy as np

def index_at(idx, shape, axis=-1):
    if axis<0:
        axis += len(shape)
    shape = shape[:axis] + shape[axis+1:]
    index = list(np.ix_(*[np.arange(n) for n in shape]))
    index.insert(axis, idx)
    return tuple(index)

a = np.random.randint(0, 10, (3, 4, 5))

axis = 1
idx = np.argmax(a, axis=axis)
print a[index_at(idx, a.shape, axis=axis)]
print np.max(a, axis=axis)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM