从每行添加不同数量的元素

时间:2013-04-25 12:57:55

标签: matlab vectorization

我有一个主矩阵,比如说

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

2 个答案:

答案 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个百万元素......

现在,你真的想要避免那个循环吗?