Row sums by vector indices without for loop?

Best illustrated by example
M=rand(5,10);
s=[1 3; 5 8; 9 10];
for i=1:size(s,1)
sm(:,i)=sum(M(:,s(i,1):s(i,2)),2);
end
Is there a one-liner or short-cut for the for loop? I do not know how large M or s is ahead of time, or their values. Above code shown only for illustration of problem trying to solve.
Thanks!
edit: Corrected typo of 'm' in for-loop to 'M'

 採用された回答

Walter Roberson
Walter Roberson 2011 年 2 月 7 日

0 投票

If your accuracy requirements are not high and your values are not extreme, you can use cumsum(), after which it becomes the difference of the cumsum indexed at two positions -- a transformation that gets around the problem that your indices do not always designate the same number of elements to be summed per row.
If I recall collectly, Bruno, and Matt Fig, both have posted non-cumsum() versions of this task in the past (it has come up before in cssm discussions.)

2 件のコメント

Oleg Komarov
Oleg Komarov 2011 年 2 月 7 日
There's a submission by Bruno, mcolon, which will allow you to create the indexes and use accumarray avoiding the multiple call to sum.
Mike Sheppard
Mike Sheppard 2011 年 2 月 8 日
I like the cumsum solution for its simplicity.
cm=cumsum([zeros(size(M,1),1) M],2);
sm2=cm(:,s(:,2)+1)-cm(:,s(:,1))
Just had to add a column of zeros; but I like the calculus F(b)-F(a)intuitive solution. Thanks!

サインインしてコメントする。

その他の回答 (1 件)

Bruno Luong
Bruno Luong 2011 年 2 月 7 日

2 投票

Yes, to be more specific my mcolon on FEX
can be used like this:
% Data
M = ceil(10*rand(5,10))
s = [1 3; 5 8; 9 10];
% Engine
[a i] = mcolon(s(:,1),s(:,2));
[r c] = ndgrid(1:size(M,1),i);
Ma = M(:,a);
sm = accumarray([r(:) c(:)], Ma(:))
Bruno

2 件のコメント

Jan
Jan 2011 年 2 月 7 日
Did you compare the speed with the OP's FOR loop method with adding a pre-allocation?
Bruno Luong
Bruno Luong 2011 年 2 月 8 日
Following Jan's question: I make the following test and I get the 25% acceleration by using MCOLON
Time relative for-loop/mcol = 1.26013/1
% Code
ntest = 10;
t = zeros(2,ntest);
for n=1:ntest
s = ceil(10*rand(1,2*10000));
s = cumsum(s);
s = reshape(s, 2, [])';
M=rand(5,s(end));
% for loop Engine
tic
sm = zeros(size(M,1),size(s,1));
for i=1:size(s,1)
sm(:,i)=sum(M(:,s(i,1):s(i,2)),2);
end
t(1,n) = toc;
% mcolon Engine
tic
[a c] = mcolon(s(:,1),s(:,2));
[r c] = ndgrid(1:size(M,1),c);
Ma = M(:,a);
sm = accumarray([r(:) c(:)], Ma(:));
t(2,n) = toc;
end
t = min(t,[],2);
t = t/min(t);
fprintf('Time relative for-loop/mcol = %g/%g\n', t);

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeProgramming についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by