2013-04-25 17 views
4

我有一个主要基质,说添加了不同数量的元素,从各行

A=magic(5); 

,也是一个载体

v=[1;3;5;2;2]; 

我想补充一个在逐行元素这样:从v(1)st元素到结尾添加第一行,从v(2)rd元素到结尾添加第二行,从v(3)元素到结束添加第三行,依此类推。

我知道我可以使用for-loop来做到这一点。但我想知道是否有矢量化的方式来做到这一点。

编辑: 让我澄清一下我用一个例子问题: 假设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

如果您发布我们可以剪切和粘贴的有效Matlab代码片段,帮助您更容易。不得不修改你的A的定义,以便Matlab接受它是一个阻力。 – 2013-04-25 13:18:50

回答

4

您可以沿行使用cumsum。该解决方案是一个有点复杂,所以我会用一个简单的例子开始:

假设你要总结,直到(含)v(i)个地方Ai个行的所有元素:res_i = \ sum_ {K = 1..v(I)} A_ik现在

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相应

[m n] = size(A); 
fA = fliplr(A); 
fv = n + 1 - v; % flip the meaning of v 
csA = cumsum(fA, 2); 
res = csA(sub2ind([m n], 1:m, fv)); % should do the trick... 
+0

非常好的解决方案和设计比我的面具更好,因为将使用更少的内存。 – Oleg 2013-04-25 13:43:32

+2

@OlegKomarov:没有理由删除你的解决方案...我想upvote它! – 2013-04-25 13:45:34

+1

@Shai我认为你错过了一个转置:'res = csA(sub2ind([mn],1:m,fv'));'as'v'是一个列向量 – Dan 2013-04-25 13:47:21

3

我知道这有点欺骗,但如何:

% 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 

S = arrayfun(@(ii) sum(A(ii, v(ii):end)), 1:size(A,1)).'; 

我通常使用时arrayfun,但比较时感到有点疲惫

所以,arrayfun毕竟不算太坏。

但这里有一个重要的观点:从远处看实现。循环解决方案是多么容易阅读/理解?矢量化解决方案如何?

考虑到这一点,也看看表演。这是一个为5000x5000矩阵......这是25个亿元素有...

现在,你会真的想避免这种循环?

+0

你比较循环和'arrayfun'的性能?这两种解决方案都不是代码的矢量化? – Shai 2013-04-25 13:58:57

+0

@Shai:嗯,我从“我知道这是作弊”开始,是不是? :)但是,从某种意义上讲,'arrayfun'是一个*任意*循环的向量化,就像'cumsum'是一个*特定*循环的向量化一样。特别是在'gpuArray'的上下文中,'arrayfun'实际上比cumsum更'*矢量化',因为它也会被矢量处理。但是,好的,我会在一分钟内为您的方法添加一个比较。 – 2013-04-25 14:21:28

+0

@Shai:另外,你知道[这个问题](http://stackoverflow.com/questions/12522888/arrayfun-can-be-significantly-slower-than-an-explicit-loop-in-matlab-why),对?因此,比较循环与'arrayfun' * always *是否合理,如果'arrayfun'要替换循环。 – 2013-04-25 14:29:16