我有一个 n×m 矩阵,我想将它转换为一个 mn×m 矩阵,结果的每个 m×m 块都包含每行的对角线。
例如,如果输入是:
[1 2; 3 4; 5 6]
输出应该是:
[1 0; 0 2; 3 0; 0 4; 5 0; 0 6]
当然,我不想自己用for
循环一步步组装矩阵。
有没有一种矢量化和简单的方法来实现这一点?
我有一个 n×m 矩阵,我想将它转换为一个 mn×m 矩阵,结果的每个 m×m 块都包含每行的对角线。
例如,如果输入是:
[1 2; 3 4; 5 6]
输出应该是:
[1 0; 0 2; 3 0; 0 4; 5 0; 0 6]
当然,我不想自己用for
循环一步步组装矩阵。
有没有一种矢量化和简单的方法来实现这一点?
对于执行此操作的矢量化方式,将对角元素的线性索引创建到结果矩阵中,并直接分配。
%# create some input data
inArray = [10 11;12 13;14 15];
%# make the index array
[nr,nc]=size(inArray);
idxArray = reshape(1:nr*nc,nc,nr)';
idxArray = bsxfun(@plus,idxArray,0:nr*nc:nr*nc^2-1);
%# create output
out = zeros(nr*nc,nc);
out(idxArray) = inArray(:);
out =
10 0
0 11
12 0
0 13
14 0
0 15
这是一个简单的矢量化解决方案,假设X
是输入矩阵:
Y = repmat(eye(size(X, 2)), size(X, 1), 1);
Y(find(Y)) = X;
另一种选择是使用sparse
,这可以写成一个简洁的单行:
Y = full(sparse(1:numel(X), repmat(1:size(X, 2), 1, size(X, 1)), X'));
我看到的最简单的方法实际上非常简单,使用简单的索引引用和 reshape 函数:
I = [1 2; 3 4; 5 6];
J(:,[1,4]) = I;
K = reshape(J',2,6)';
如果你检查J
,它看起来像这样:
J =
1 0 0 2
3 0 0 4
5 0 0 6
矩阵K
正是想要的:
K =
1 0
0 2
3 0
0 4
5 0
0 6
正如 Eitan T 在评论中指出的那样,以上内容特定于示例,并不涵盖一般解决方案。因此,以下是一般解决方案,其中 m 和 n 如问题中所述。
J(:,1:(m+1):m^2) = I;
K=reshape(J',m,m*n)';
如果您想测试它以查看它的工作原理,只需使用
I=reshape(1:(m*n),m,n)';
注意:如果 J 已经存在,这可能会导致问题。在这种情况下,您还需要使用
J=zeros(n,m^2);
它可能不是计算效率最高的解决方案,但这里有一个 1-liner 使用kron
:
A = [1 2; 3 4; 5 6];
B = diag(reshape(A', 6, 1) * kron(ones(3, 1), eye(2))
% B =
% 1 0
% 0 2
% 3 0
% 0 4
% 5 0
% 0 6
如果 A 是 nxm,这可以概括为:
diag(reshape(A.', n*m, 1)) * kron(ones(n,1), eye(m))