2013-04-25 16 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