Python: 多维数组掩码

2 投票
1 回答
1033 浏览
提问于 2025-04-17 10:40

下面这段代码在Matlab中是这样的,我们想知道在Python中怎么写才能达到同样的效果。

Matlab:


B = 2D array of integers as indices [1...100]
A = 2D array of numbers: [10x10]
A[B] = 0

这段代码运行得很好,比如当你写 B[i]=42 时,它能找到第 5 列的第 2 行来进行设置。

但是在Python中,如果这样写就会出现错误:超出范围,这也是合理的。不过我们想把上面的Matlab代码转换成Python,所以需要找到更符合Python风格的方法。

另外,我们还要考虑更高维度的问题,比如:


B = 2D array of integers as indices [1...3000]
C = 3D array of numbers: [10x10x30]
C[B] = 0

我们想到的一种方法是把索引数组的元素改成 i,j 这样的形式,而不是绝对位置。也就是说,把位置 42 转换成 divmod(42,m=10)[::-1] >>> (2,4)。这样我们就可以得到一个 nx2 >>> ii,jj 的索引向量,这样在索引 A 时会更方便。

我们觉得这种方法可能更好,而且在Python中对于更高维度的情况也会更高效。

1 个回答

4

你可以在对数组(A)进行索引之前,先用 .ravel() 把它变成一维的,然后再用 .reshape() 来调整它的形状。

另外,因为你知道 A.shape 的形状信息,你也可以在对另一个数组(B)进行索引之前,使用 np.unravel_index

示例 1:

>>> import numpy as np
>>> A = np.ones((5,5), dtype=int)
>>> B = [1, 3, 7, 23]
>>> A
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]])
>>> A_ = A.ravel()
>>> A_[B] = 0
>>> A_.reshape(A.shape)
array([[1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 1]])

示例 2:

>>> b_row, b_col = np.vstack([np.unravel_index(b, A.shape) for b in B]).T
>>> A[b_row, b_col] = 0
>>> A
array([[1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 1]])

后来发现:你还可以使用 numpy.put

>>> import numpy as np
>>> A = np.ones((5,5), dtype=int)
>>> B = [1, 3, 7, 23]
>>> A.put(B, [0]*len(B))
>>> A
array([[1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 0, 1]])

撰写回答