In [1]: import numpy as np
In [2]: a = np.array([[2,0],[3,0],[3,1],[5,0],[5,1],[5,2]])
In [3]: b = np.zeros((6,3), dtype='int32')
In [4]: b[a[:,0], a[:,1]] = 10
In [5]: b
Out[5]:
array([[ 0, 0, 0],
[ 0, 0, 0],
[10, 0, 0],
[10, 10, 0],
[ 0, 0, 0],
[10, 10, 10]])
为什么有效:
如果您在分配中b使用两个numpy 数组进行索引,
b[x, y] = z
然后将 NumPy 想象为同时在 的每个元素x和每个y元素上移动z(我们称它们为xval,yval和zval),并将值分配给 b[xval, yval] zval。当是一个常数,“每次z移动只是返回相同的值。z
这就是我们想要的,x成为 的第一列a和y第二列a。因此,选择x = a[:, 0]和y = a[:, 1]。
b[a[:,0], a[:,1]] = 10
为什么b[a] = 10不起作用
当您编写 时b[a],将 NumPy 视为通过移动 , 的每个元素a(让我们称其为每个元素idx)并将新数组中的值放入 in 的位置b[idx]来创建一个新数组。idxa
idx是 中的一个值a。所以它是一个int32。 b是形状 (6,3),所以b[idx]是一排b形状 (3,)。例如,什么idx时候
In [37]: a[1,1]
Out[37]: 0
b[a[1,1]]是
In [38]: b[a[1,1]]
Out[38]: array([0, 0, 0])
所以
In [33]: b[a].shape
Out[33]: (6, 2, 3)
所以让我们重复一遍:NumPy 正在创建一个新数组,方法是在新数组中移动 in 的每个元素a并将 in 的值放入新数组b[idx]中。随着移动,将创建一个形状数组 (6,2)。但由于它本身的形状为 (3,),因此在 (6,2) 形状的数组中的每个位置,都会放置一个 (3,) 形状的值。结果是一个形状数组 (6,2,3)。idxaidxab[idx]
现在,当你做一个像
b[a] = 10
创建一个具有值的临时形状 (6,2,3) 数组b[a],然后执行分配。由于 10 是一个常数,因此该赋值将值 10 放置在 (6,2,3) 形数组中的每个位置。然后将临时数组中的值重新分配回b. 请参阅对文档的参考。因此 (6,2,3) 形数组中的值被复制回 (6,3) 形b数组。值相互覆盖。但重点是你没有得到你想要的任务。