take line sum of part of matrix
1 view (last 30 days)
Show older comments
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!
0 Comments
Accepted Answer
Daniel Shub
on 25 Sep 2012
Edited: Daniel Shub
on 25 Sep 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 Comments
Daniel Shub
on 3 Oct 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
on 3 Oct 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.
More Answers (3)
Thomas
on 25 Sep 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
0 Comments
Andrei Bobrov
on 25 Sep 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));
0 Comments
See Also
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!