【问题标题】:Numpy assignment like 'numpy.take'像'numpy.take'这样的numpy分配
【发布时间】:2017-07-28 04:05:51
【问题描述】:

是否可以按照 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 对此有一些有限的(一维)支持,但我想知道是否有更简洁的方法来做到这一点?

【问题讨论】:

  • a[:,inds] = 0 怎么样?
  • 重点是我希望能够以编程方式执行a[inds, :] = 0a[:, inds] = 0 或(在 3-D 情况下)a[:, :, inds] = 0 等,而无需编写一堆 if声明

标签: python arrays numpy indexing


【解决方案1】:
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 是不必要的,但在其他情况下可能有用。

【讨论】:

  • 您似乎忽略了axis 参数的使用。
  • 谢谢!如果put 在轴参数方面具有类似的功能,那就太好了,但是索引元组的构造对我有用
  • 这是一个不需要知道数组的ndim的索引构造的便利函数:def put_at(inds, axis=-1, slc=(slice(None),)): return (axis&lt;0)*(Ellipsis,) + axis*slc + (inds,) + (-1-axis)*slca[put_at(ind_list,axis=axis)]一样使用。 @hpaulj 如果通过审核,请随时将其添加到您的帖子中。
【解决方案2】:

我已经给出了一个使用的例子 numpy.take in 2 dimensions。也许你可以根据你的问题调整它

【讨论】:

    【解决方案3】:

    您可以通过这种方式使用索引:

    a[:,[1,2]]=0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-10
      • 2020-08-26
      相关资源
      最近更新 更多