take line sum of part of matrix

1 visualizzazione (ultimi 30 giorni)
Mat
Mat il 25 Set 2012
Hi all!
I'm trying to use (as always) vectorized commands but came to a problem which looks quite simple at the beginning. Let me give you an example.
A = [1, 2, 54, 4, 5, 6; ...
1, 2, 88, 4, 5, 6; ...
1, 2, 0, 4, 5, 6; ]; % identical rows except for column 3
b = [5;2;6];
The values in b give the last column in A I want to build the line-sum for: My result should give me
c = ??? = [1+2+54+4+5;
1+2;
1+2+0+4+5+6];
Thank you for your help!

Risposta accettata

Daniel Shub
Daniel Shub il 25 Set 2012
Modificato: Daniel Shub il 25 Set 2012
There are a number of ways to do this. A fully vectorized way is with cumsum, but it has a lot of extra calculations so may not be best, especially since MATLAB loops are no longer slow.
A = [1, 2, 54, 4, 5, 6; ...
1, 2, 88, 4, 5, 6; ...
1, 2, 0, 4, 5, 6; ];
b = [5;2;6];
Then get the cumulative sum of each row from the beginning to the end.
x = cumsum(A')';
Then extract the values you want.
x(sub2ind(size(x), 1:3, b'))
Solution 2
Give the rows are all identical except for the third column, you can cheat a little bit. If we leave out the 3rd column, then we only need to sum the first row up to the max of b.
maxb = max(b);
n = 3;
x = cumsum(A(1, [1:(n-1), (n+1):maxb]))';
If every element of b was less than 3, we could do
x(b)
If the every element of b was greater than or equal to 3, we could do something like
x(b-1)+*A(:, 3)
where we need to subtract the 1 from the index to account for the fact that we skipped the third column. These two statements can be combined into a single statement with a weight vector that tells us if b is greater or less than 3 (n).
w = (b >= n);
Then we adjust the indices
c = b;
c(w) = b(w)-1;
and finally get the answer
x(c)+w.*A(:, 3)
  4 Commenti
Daniel Shub
Daniel Shub il 3 Ott 2012
Of course it is. I am curious as to what lead me to that strange construct and why I didn't notice.
Matt Fig
Matt Fig il 3 Ott 2012
Mat,
I find ARRAYFUN almost always slower than loops and CELLFUN almost always faster. Strange but true. CELLFUN with the string args is very fast indeed.

Accedi per commentare.

Più risposte (3)

Matt Fig
Matt Fig il 25 Set 2012
Modificato: Matt Fig il 25 Set 2012
Another:
% Given data
A = [1, 2, 54, 4, 5, 6;...
1, 2, 88, 4, 5, 6;...
1, 2, 0, 4, 5, 6];
b = [5;2;6];
% The method
R = size(A,1); % Just to be general.
S = cumsum(A,2); % The cumulative sum.
S = S((1:R).' + (b-1)*R) % The desired values.

Thomas
Thomas il 25 Set 2012
A = [1, 2, 54, 4, 5, 6; 1, 2, 88, 4, 5, 6; 1, 2, 0, 4, 5, 6; ];
b = [5;2;6];
for ii=1:length(b)
sumA(ii)=sum(A(ii,1:b(ii)));
end
sumA

Andrei Bobrov
Andrei Bobrov il 25 Set 2012
A = [1, 2, 54, 4, 5, 6; ...
1, 2, 88, 4, 5, 6; ...
1, 2, 0, 4, 5, 6; ];
b = [5;2;6];
s = size(A);
q = zeros(s);
q((b - 1)*s(1) + (1:s(1))') = 1;
i1 = bsxfun(@times,fliplr(cumsum(fliplr(q),2)),(1:s(1))');
t = i1>0;
out = accumarray(i1(t),A(t));

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by