我试图将名为“S”的2D numpy数组的一部分替换为i和j的函数。鉴于S为:
>>> S
Out[1]:
array([[ 1., 0., 0.],
[ 0., 3., 0.],
[ 0., 0., 9.]]
对于i = 0和j = 1,我可以使用以下语法访问元素行i和j以及列i和j:
>>> S[:, [i, j]][[i, j], :]
Out[2]:
array([[ 1., 0.],
[ 0., 3.]])
现在,当我尝试用相同维度的另一个数组(tmp_arr)替换数组S的相同元素时,python不会给出错误,但它也没有做任何意味着S的元素保持不变且没有错误消息显示。
>>> tmp_arr
Out[3]:
array([[ 555., 0.],
[ 0., 555.]])
>>> S[:, [i, j]][[i, j], :] = tmp_arr
我得到的是相同的矩阵:
>>> S
Out[4]:
array([[ 1., 0., 0.],
[ 0., 3., 0.],
[ 0., 0., 9.]])
显然以下方法可行,但我正在寻找一个优雅的解决方案:
S[i, i] = tmp_arr[0, 0]
S[i, j] = tmp_arr[0, 1]
S[j, i] = tmp_arr[1, 0]
S[j, j] = tmp_arr[1, 1]
感谢您的意见和经验。
答案 0 :(得分:3)
您可以使用np.ix_
构建所需的索引数组:
In [91]: S[np.ix_([i,j],[i,j])]
Out[91]:
array([[1, 0],
[0, 3]])
In [92]: tmp_arr = np.eye(2)*555
In [93]: tmp_arr
Out[93]:
array([[ 555., 0.],
[ 0., 555.]])
In [94]: S[np.ix_([i,j],[i,j])] = tmp_arr
In [95]: S
Out[95]:
array([[555, 0, 0],
[ 0, 555, 0],
[ 0, 0, 9]])
使用np.ix_
有助于对S
进行分配,但请注意,有更快的方法可以选择子阵列:
In [99]: %timeit S.take([i, j], axis=1).take([i, j], axis=0)
100000 loops, best of 3: 3.32 µs per loop
In [97]: %timeit S[:, [i, j]][[i, j], :]
100000 loops, best of 3: 8.8 µs per loop
In [96]: %timeit S[np.ix_([i,j],[i,j])]
100000 loops, best of 3: 13 µs per loop
但与其他方法不同,S[np.ix_(...)] = ...
不使用链式索引,因此调用S.__setitem__
并且分配会影响S
。相比之下,S[:, [i, j]]
会返回S
子数组的副本,因此分配给S[:, [i, j]][[i, j], :]
只影响子数组的副本,而不是S
本身。由于不保留对子数组副本的引用,因此Python在分配完成后会抛弃副本,因此分配将丢失。这就是为什么链式索引不适合分配给S
。
答案 1 :(得分:0)
>>> a
array([[ 1., 0., 0.],
[ 0., 3., 0.],
[ 0., 0., 9.]])
>>> i, j = 0 , 1
>>> a[i:j+1,i:j+1] = np.arange(100, 104).reshape(2,2)
>>> a
array([[ 100., 101., 0.],
[ 102., 103., 0.],
[ 0., 0., 9.]])
>>>