首页 > 解决方案 > 使用掩码的逻辑索引在 numpy 中工作,而不是在 Matlab 中

问题描述

我正在尝试使用稀疏矩阵在 MATLAB 中重现以下 Python 代码。

>>> print(M)
[[0 0 0 0 0]
 [0 1 1 1 0]
 [0 1 0 1 0]
 [0 1 1 1 0]
 [0 0 0 0 0]]
>>> im2var = np.arange(5 * 5).reshape((5, 5))
>>> A = np.zeros((25, 25), dtype=int)
>>> A[im2var[M == 1], im2var[M == 1]] = 1
>>> print(A)
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

这是我在 MATLAB 中写的

M = [
    0 0 0 0 0;
    0 1 1 1 0;
    0 1 0 1 0;
    0 1 1 1 0;
    0 0 0 0 0
];

im2var = reshape(1:25, [5 5]);
A = zeros(25, 25);
A(im2var(M == 1), im2var(M == 1)) = 1;
num2str(A)

当我运行 MATLAB 脚本时,我得到以下矩阵,这与 Numpy 输出明显不同。

ans =

  25x73 char array

    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  1  1  0  0  1  0  1  0  0  1  1  1  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'

感谢您的帮助!

编辑:我也想完成以下效果,但目前的答案似乎不适用于两组索引。

在 Python 中:

>>> Mp = np.roll(M, 1, axis=1)
>>> A[im2var[M==1], im2var[Mp==1]] = -1
>>> print(A[5:15,5:15])
[[ 0  0  0  0  0  0  0  0  0  0]
 [ 0  1 -1  0  0  0  0  0  0  0]
 [ 0  0  1 -1  0  0  0  0  0  0]
 [ 0  0  0  1 -1  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  1 -1  0  0]
 [ 0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  1 -1]
 [ 0  0  0  0  0  0  0  0  0  0]]

通过使用当前答案的建议,我编写了以下代码。

M = [
    0 0 0 0 0;
    0 1 1 1 0;
    0 1 0 1 0;
    0 1 1 1 0;
    0 0 0 0 0
];

Mp = circshift(M, 1, 2);

ind = find(M);
indp = find(Mp);

A = zeros(25, 25);
A(sub2ind(size(A), ind, ind)) = 1;
A(sub2ind(size(A), ind, indp)) = -1;

num2str(A)

虽然对角线 1 已成功出现,但 -1 出现在错误的位置。

ans =

  25x73 char array

    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  1  0  0  0  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  1  0  0  0  0 -1  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  1  0  0  0  0 -1  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0 -1  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0 -1  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0 -1  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0 -1  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0 -1  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0'

编辑2:

根据编辑的答案,我尝试了以下代码。

M = [
    0 0 0 0 0;
    0 1 1 1 0;
    0 1 0 1 0;
    0 1 1 1 0;
    0 0 0 0 0
];

Mp = circshift(M, 1, 2);

ind = find(M);
indp = find(Mp.');

A = zeros(25, 25);
A(sub2ind(size(A), ind, ind)) = 1;
A(sub2ind(size(A), ind, indp)) = -1;

num2str(A(5:14, 5:14))

但它仍然不会产生与 EDIT 1 中的 Python 代码相同的结果。

ans =

  10x28 char array

    '0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0'
    '0  0  1 -1  0  0  0  0  0  0'
    '0  0  0  1 -1  0  0  0  0  0'
    '0  0  0  0  1 -1  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  1 -1  0'
    '0  0  0  0  0  0  0  0  0  0'
    '0  0  0  0  0  0  0  0  0  1'

标签: pythonmatlabnumpymatrix-indexing

解决方案


在 MATLAB 中,您可以获得目标位置A返回的相关行和列下标。im2var(M == 1)这可以find(M.')在不需要初始化的情况下交替完成,im2var或者只是find(M)因为在你的情况下M等于transpose(M)find(M)返回线性索引,其中M不为零,但 的线性索引与M的行和列下标相同A。您不能直接使用这些行和列下标,需要将它们转换为线性索引,然后继续,即

ind = find(M);     % ind = find(M.'); in general
A(sub2ind(size(A),ind,ind)) = 1;

PS:请注意,MATLAB 遵循列主要顺序,而 NumPy 遵循行主要顺序。


推荐阅读