我有一个主矩阵,比如说
A=magic(5);
还有一个载体
v=[1;3;5;2;2];
我想以这种方式逐行添加A的元素:将第一行从v(1)st元素添加到结尾,第二行从v(2)rd元素添加到结尾,第三行从第v(3)个元素到结尾,依此类推。
我知道我可以使用for循环执行此操作。但是我想知道是否有一种矢量化的方法来实现它。
修改 让我用一个例子来澄清我的问题: 假设A和v如上所述。
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
和
v =
1
3
5
2
2
现在我想要一种获得以下结果的方法:
answer =
65 % 17+24+1+8+15
37 % 7+14+16
22 % 22
55 % 12+19+21+3
54 % 18+25+2+9
答案 0 :(得分:4)
您可以沿着行使用cumsum
。解决方案有点复杂,所以我将从一个更简单的例子开始:
假设您要对i
的{{1}}行的所有元素求和,直到(包括)第A
位:res_i = \ sum_ {k = 1 .. v(i)} A_ik
v(i)
现在,对于您的问题,由于您需要从 m = size(A,1); % num of rows
csA = cumsum(A, 2); % cumsum along rows
res = csA( sub2ind( size(A), 1:m, v ) ); % pick the vi-th column for the i-th row
到所有元素的总和,我们需要翻转v(i)
并更改A
相应
v
答案 1 :(得分:3)
我知道这有点作弊,但是怎么样:
S = arrayfun(@(ii) sum(A(ii, v(ii):end)), 1:size(A,1)).';
通常我在使用arrayfun
时有点厌倦,但比较时:
% sample data
N = 5000;
A = magic(N);
v = randi(N, N,1);
% simple loop
tic
S = zeros(N,1);
for ii = 1:N
S(ii) = sum(A(ii, v(ii):end));
end
toc
% arrayfun solution
tic
S = arrayfun(@(ii) sum(A(ii, v(ii):end)), 1:N).';
toc
% Shai's solution
tic
[m n] = size(A);
fA = fliplr(A);
fv = n + 1 - v;
csA = cumsum( fA, 2 );
res = csA( sub2ind( [m n], 1:m, fv.' ) ).';
toc
结果:
Elapsed time is 0.386280 seconds. % simple loop
Elapsed time is 0.473916 seconds. % arrayfun
Elapsed time is 0.495794 seconds. % Shai's solution
所以,arrayfun
毕竟不是太糟糕。
但这里有一个重点:从远处看一下实现。循环解决方案有多容易理解/理解?矢量化解决方案怎么样?
考虑到这一点,还要看一下表演。这是一个5000x5000矩阵......那里有25个百万元素......现在,你真的想要避免那个循环吗?