是否可以按照take功能的工作方式分配给numpy数组?

例如。如果我有一个数组a,索引列表inds和所需的轴,则可以使用take,如下所示:

import numpy as np
a = np.arange(12).reshape((3, -1))
inds = np.array([1, 2])
print(np.take(a, inds, axis=1))

[[ 1  2]
 [ 5  6]
 [ 9 10]]

当所需的索引/轴可能在运行时更改时,此功能非常有用。

但是,numpy不允许您这样做:
np.take(a, inds, axis=1) = 0
print(a)

似乎通过numpy.put对此提供了一些有限的(1-D)支持,但是我想知道是否有更干净的方法可以做到这一点?

最佳答案

In [222]: a = np.arange(12).reshape((3, -1))
     ...: inds = np.array([1, 2])
     ...:
In [223]: np.take(a, inds, axis=1)
Out[223]:
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])
In [225]: a[:,inds]
Out[225]:
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])

构造一个索引元组
In [226]: idx=[slice(None)]*a.ndim
In [227]: axis=1
In [228]: idx[axis]=inds
In [229]: a[tuple(idx)]
Out[229]:
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])
In [230]: a[tuple(idx)] = 0
In [231]: a
Out[231]:
array([[ 0,  0,  0,  3],
       [ 4,  0,  0,  7],
       [ 8,  0,  0, 11]])

a[inds,:]:
In [232]: idx=[slice(None)]*a.ndim
In [233]: idx[0]=inds
In [234]: a[tuple(idx)]
Out[234]:
array([[ 4,  0,  0,  7],
       [ 8,  0,  0, 11]])
In [235]: a[tuple(idx)]=1
In [236]: a
Out[236]:
array([[0, 0, 0, 3],
       [1, 1, 1, 1],
       [1, 1, 1, 1]])

PP的建议:
def put_at(inds, axis=-1, slc=(slice(None),)):
    return (axis<0)*(Ellipsis,) + axis*slc + (inds,) + (-1-axis)*slc

用作a[put_at(ind_list,axis=axis)]
我已经在numpy函数上看到了这两种样式。这看起来像是用于extend_dims的代码,我的是用于apply_along/over_axis的代码。

较早的想法

在最近的take问题中,我/我们发现对于某些困惑的索引,它等效于arr.flat[ind]。我得查一下。

有一个np.put与分配给flat等效:
Signature: np.put(a, ind, v, mode='raise')
Docstring:
Replaces specified elements of an array with given values.

The indexing works on the flattened target array. `put` is roughly
equivalent to:

    a.flat[ind] = v

它的文档中还提到了placeputmask(以及copyto)。

numpy multidimensional indexing and the function 'take'

我评论了take(无轴)等效于:
lut.flat[np.ravel_multi_index(arr.T, lut.shape)].T

ravel:
In [257]: a = np.arange(12).reshape((3, -1))
In [258]: IJ=np.ix_(np.arange(a.shape[0]), inds)
In [259]: np.ravel_multi_index(IJ, a.shape)
Out[259]:
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]], dtype=int32)
In [260]: np.take(a,np.ravel_multi_index(IJ, a.shape))
Out[260]:
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])
In [261]: a.flat[np.ravel_multi_index(IJ, a.shape)] = 100
In [262]: a
Out[262]:
array([[  0, 100, 100,   3],
       [  4, 100, 100,   7],
       [  8, 100, 100,  11]])

并使用put:
In [264]: np.put(a, np.ravel_multi_index(IJ, a.shape), np.arange(1,7))
In [265]: a
Out[265]:
array([[ 0,  1,  2,  3],
       [ 4,  3,  4,  7],
       [ 8,  5,  6, 11]])

在这种情况下,无需使用ravel,但在其他情况下则可能有用。

关于python - 像 'numpy.take'这样的数字任务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42656930/

10-12 01:54