take line sum of part of matrix
1 回表示 (過去 30 日間)
古いコメントを表示
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 件のコメント
採用された回答
Daniel Shub
2012 年 9 月 25 日
編集済み: Daniel Shub
2012 年 9 月 25 日
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 件のコメント
Daniel Shub
2012 年 10 月 3 日
Of course it is. I am curious as to what lead me to that strange construct and why I didn't notice.
Matt Fig
2012 年 10 月 3 日
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.
その他の回答 (3 件)
Thomas
2012 年 9 月 25 日
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 件のコメント
Andrei Bobrov
2012 年 9 月 25 日
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 件のコメント
参考
カテゴリ
Help Center および File Exchange で Logical についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!