【问题标题】:Replacing part of a 2D numpy array using indexing使用索引替换 2D numpy 数组的一部分
【发布时间】:2014-10-01 06:29:45
【问题描述】:

我正在尝试将名为“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]

感谢您的 cmets 和经验。

【问题讨论】:

    标签: python numpy indexing multidimensional-array


    【解决方案1】:

    您可以使用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

    【讨论】:

    • 谢谢@unutbu 的回答。这绝对是有道理的。
    【解决方案2】:
    >>> 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.]])
    >>> 
    

    【讨论】:

    • 为了确保他只抓住他所追求的 4 件物品,您必须这样做 a[i:j+1:j-i, i:j+1:j-i],不是吗?当然,请确保 j > i.
    • 请注意 i ,j 可以是非连续的。例如 i=0 和 j=2。换句话说,如果我要替换 S[0,0]、S[0,2]、S[2,0] 和 S[2,2],那么我认为上述解决方案不会奏效。如果我错了,请纠正我。
    • @Arian,你是对的 - 我的解决方案将 替换 一个连续的范围。不幸的是,这不是我的第一个误解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2022-07-08
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 2019-12-23
    相关资源
    最近更新 更多