如何在Numpy数组中设置单个索引

时间:2018-06-30 00:13:53

标签: python python-3.x numpy

我正在尝试使用数组在其他数组中设置值。不幸的是,与其设置值,不如以某种方式覆盖一堆值。发生了什么,如何实现我想要的?

>>> target = np.array( [ [0,1],[1,2],[2,3] ])
>>> target
array([[0, 1],
       [1, 2],
       [2, 3]])
>>> actions = np.array([0,0,0])
>>> target[actions] #The first row, 3 times
array([[0, 1],
       [0, 1],
       [0, 1]])
>>> target[:,actions] #The first column, 3 times
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2]])
>>> values = np.array([7,8,9])
>>> target[:,actions] = values #why isnt this working?
>>> target
array([[9, 1],
       [9, 2],
       [9, 3]])
#Actually want
#array([[7, 1],
#       [8, 2],
#       [9, 3]])

>>> target = np.array( [ [0,1],[1,2],[2,3] ]) #reset to original value
>>> actions = np.array([0,1,0])
>>> target[:,actions] = values.reshape(3, 1)
array([[7, 7],
       [8, 8],
       [9, 9]])
#Actually want
#array([[7, 1],
#       [1, 8],
#       [9, 3]])

3 个答案:

答案 0 :(得分:1)

target[:,actions]选择target中相同列的三次。

您说target[:,actions] = values时,您正在做的是:

  1. 将7分配给该列中的所有值,三次。
  2. 将8分配给该列中的所有值,三次。
  3. 将9分配给该列中的所有值,三次。

因此,该列中的所有值都以9结尾。

如果您坚持要进行这种笨拙的三重数据写入,则可以通过转置写入来解决它:

target[:,actions] = values.reshape(3, 1)

这将[7,8,9]写入该列三次。显然这很浪费,您可以改为这样做:

target[:,actions[-1]] = values

效果应该相同,并且可以节省计算。

答案 1 :(得分:1)

将[7,8,9]写入第一列的2种方法:

基本索引(带切片):

In [396]: target[:,0] = [7,8,9]           # all rows, 1st column
In [397]: target
Out[397]: 
array([[7, 1],
       [8, 2],
       [9, 3]])

高级索引编制(带有2个列表)

In [398]: target[[0,1,2],[0,0,0]] = [7,8,9]   # pair [0,0],[1,0],[2,0]
In [399]: target
Out[399]: 
array([[7, 1],
       [8, 2],
       [9, 3]])

第二种方法也适用于混合列:

In [400]: target = np.array( [ [0,1],[1,2],[2,3] ])
In [401]: target[[0,1,2],[0,1,0]] = [7,8,9]
In [402]: target
Out[402]: 
array([[7, 1],
       [1, 8],
       [9, 3]])

广播开始。在这种情况下,有3个可能要广播的数组-2维和源数组。

像这样的高级索引会生成一个1d数组。因此源数组必须匹配:

In [403]: target[[0,1,2],[0,1,0]]
Out[403]: array([7, 8, 9])

(1,3)可以广播到(3,),但是(3,1)不能:

In [404]: target[[0,1,2],[0,1,0]] = np.array([[7,8,9]])
In [405]: target[[0,1,2],[0,1,0]] = np.array([[7,8,9]]).T
...
ValueError: shape mismatch: value array of shape (3,1) could not be broadcast to indexing result of shape (3,)

这种索引是不寻常的。请注意,结果是(3,3)。

In [412]: target[:,[0,0,0]]
Out[412]: 
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2]])

A(3,1)来源:

In [413]: np.array([[7,8,9]]).T
Out[413]: 
array([[7],
       [8],
       [9]])
In [414]: target[:,[0,0,0]] = _
In [415]: target
Out[415]: 
array([[7, 1],
       [8, 2],
       [9, 3]])

(3,1)可以广播到(3,3)。它可以工作,但最终将[7,8,9]分配了3次,全部分配给相同的0列。


分配第一列的另一种方法:

In [423]: target[np.ix_([0,1,2],[0,0,0])]
Out[423]: 
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2]])

再次获得(3,3),并接受(3,1):

In [424]: target[np.ix_([0,1,2],[0,0,0])] = np.array([[7,8,9]]).T
In [425]: target
Out[425]: 
array([[7, 1],
       [8, 2],
       [9, 3]])

ix_形成2个可以相互广播的数组,在这种情况下,它们是列向量和第1行:

In [426]: np.ix_([0,1,2],[0,0,0])
Out[426]: 
(array([[0],
        [1],
        [2]]), array([[0, 0, 0]]))

我可以选择target的所有元素:

In [430]: target[np.ix_([0,1,2],[0,1])]
Out[430]: 
array([[0, 1],
       [1, 2],
       [2, 3]])

并按混乱的顺序:

In [431]: target[np.ix_([2,0,1],[1,0])]
Out[431]: 
array([[3, 2],
       [1, 0],
       [2, 1]])

答案 2 :(得分:-1)

我无法使用:索引使其工作,但是下面的操作通过使用索引数组来实现。不确定:方法为何不起作用,如果有人可以提出一种解决方法,我会接受。

>>> target = np.array( [ [0,1],[1,2],[2,3] ])
>>> rows = np.arange(target.shape[0])
>>> actions = np.array([0,1,0])
>>> values = np.array([7,8,9])
>>> target[rows,actions] = values
>>> target
array([[7, 1],
       [1, 8],
       [9, 3]])