我有一个方阵A
,我想用矩阵D
进行操作。结果将是矩阵B
。条目B(i, j)
将是来自A(:, j)
的多个元素的总和,由D
确定。
让我展示代码中的内容 -
A = magic(3); % initial matrix
D = [1, 2, 3; 2, 2, 3; 1, 3, 1]; % map matrix
B = zeros(3); % resultant matrix
for i = 1:3
for j = 1:3
B(D(i, j), j) = B(D(i, j), j) + A(i, j);
end
end
现在,我要解释一下D
为:
D = [1, 2, 3;
2, 2, 3;
1, 3, 1];
这些D
值基本上作为行索引累积到输出数组B
,而列索引本身就是迭代数字 -
col = [1 2 3;
1 2 3;
1 2 3];
因此,总结如下:
B(1,1) += A(1,1) % Indices from first row from D to select B
B(2,2) += A(1,2)
B(3,3) += A(1,3)
B(2,1) += A(2,1) % Indices from second row from D to select B
B(2,2) += A(2,2)
B(3,3) += A(2,3)
B(1,1) += A(3,1) % Indices from third row from D to select B
B(3,2) += A(3,2)
B(1,3) += A(3,3)
因此,在B(1,1)
,我们会积累来自A
:A(1,1)
和A(3,1)
的两个值,依此类推。
当矩阵很大时,这个过程需要很长时间。有没有办法对这个计算进行矢量化?
答案 0 :(得分:3)
以下是使用accumarray
和bsxfun
-
[m,n] = size(A);
% Generate all linear indices corresponding to D
idx = bsxfun(@plus,D,m*(0:n-1))
% Use accumarray to accumulate values for each of those indices.
% We need some reshaping to get a final 2D output after feeding in column
% vectors for using accumarray
Bout = reshape(accumarray(idx(:),A(:),[m*n,1]),[m,n])
示例运行 -
>> % Setup inputs and run loopy version
A = randi(9,4,6);
D = randi(size(A,1),4,6);
B = zeros(size(A));
for i = 1:size(A,1)
for j = 1:size(A,2)
B(D(i, j), j) = B(D(i, j), j) + A(i, j);
end
end
% Proposed vectorized method
>> [m,n] = size(A);
>> idx = bsxfun(@plus,D,m*(0:n-1));
>> Bout = reshape(accumarray(idx(:),A(:),[m*n,1]),[m,n]);
% Verify results
>> max(abs(Bout(:)-B(:)))
ans =
0