Can you split a vector according to a pre-defined sequence?

5 ビュー (過去 30 日間)
Pete
Pete 2013 年 3 月 24 日
Can anyone suggest a way in which it is possible to perform operations on a vector according to a predetermined sequence - for example I have a vector of different values, M, which is < 8760x1 > in size. I have another vector with a sequence of numbers, P, (size < 300x1 >) and this sequence sums to 8760. I would like to use these P values to index the vector M and find the product of each index.
An example to make this clearer:
M = [1,2,4,2,3,4,5,3,4,2];
P = [2,2,4,2];
Result = [3,6,15,6]
Any help here would be greatly appreciated.
Peter.S.
  3 件のコメント
Image Analyst
Image Analyst 2013 年 3 月 24 日
Can you explain how you got Result? Because I don't understand. Using P as indexes of M gives [M(2), M(2), M(4), M(2)], and the product of all those i = 2*2*2*2 which equals 16, not 3 (which is Result(1)). Why do you have 4 Result elements and not just 1? On the other hand "the product of each index." would be 2*2*4*2 which is the product of all the indexes (the numbers in P), and that is 32 - again, not 3 and not [3,6,15,6].
Pete
Pete 2013 年 3 月 24 日
Sorry I'm not sure which 6 you are referring to -
Result gives the value of M(1,1)+M(1,2) =3, then M(1,3)+M(1,4) =6, then M(1,5)+M(1,6)+M(1,7)+M(1,8)=15 and M(1,9)+ M(1,10) =6

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

採用された回答

Azzi Abdelmalek
Azzi Abdelmalek 2013 年 3 月 24 日
編集済み: Azzi Abdelmalek 2013 年 3 月 24 日
M = [1,2,4,2,3,4,5,3,4,2];
P = [2,2,4,2];
id2=cumsum(P);
id1=[1 id2(1:end-1)+1];
for k=1:numel(id1)
Result(k)=sum(M(id1(k):id2(k)));
end
%or
id2=cumsum(P);
id1=[1 id2(1:end-1)+1];
Result=arrayfun(@(x,y) sum(M(x:y)),id1,id2)
  2 件のコメント
Pete
Pete 2013 年 3 月 24 日
Thankyou that does work perfectly. I also need the product of these values i.e. so the Result would now be [2,8,180,8]. Is there a similar method to achieve this?
Thanks again for your help.
Pete
Pete 2013 年 3 月 24 日
Sorry that was not a good question, simply swap the sum for prod! Thanks again!

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

その他の回答 (1 件)

Cedric
Cedric 2013 年 3 月 24 日
編集済み: Cedric 2013 年 3 月 24 日
id = zeros(numel(M), 1) ;
id(1+cumsum(P)) = 1 ;
id = 1 + cumsum(id(1:end-1)) ;
result = accumarray(id, M(:)).' ;
With the vectors M and P from your statement, this code leads to:
result =
3 6 15 6
Note that for small sizes of M and P, Azzi's solution is much more efficient than mine, and my solution becomes more efficient than his when sizes become significant.
  3 件のコメント
Cedric
Cedric 2013 年 3 月 25 日
編集済み: Cedric 2013 年 3 月 25 日
Hello Azzi, yes, in your test sum(P) is not equal to length(M).
I performed my tests on larger arrays with
n = 1000 ; % 1 for original setup.
M = repmat([1,2,4,2,3,4,5,3,4,2], 1, n) ;
P = repmat([2,2,4,2], 1, n) ;
tic ;
result_AA1 = zeros(size(P)) ;
idx=cumsum(P); ii=1; jj=P(1);
for k=1:numel(idx)
jj=P(k)+ii-1;
result_AA1(k)=sum(M(ii:jj));
ii=jj+1;
end
toc
tic ;
id2=cumsum(P);
id1=[1 id2(1:end-1)+1];
result_AA2 = arrayfun(@(x,y) sum(M(x:y)),id1,id2) ;
toc
tic ;
id = zeros(numel(M), 1) ;
id(1+cumsum(P)) = 1 ;
id = 1 + cumsum(id(1:end-1)) ;
result_CW = accumarray(id, M(:)).' ;
toc
all(result_AA2 == result_AA1 & result_CW == result_AA1)
And I obtained
Elapsed time is 0.010770 seconds.
Elapsed time is 0.031326 seconds.
Elapsed time is 0.000788 seconds.
ans =
1
EDIT: for n=1, however:
Elapsed time is 0.000036 seconds.
Elapsed time is 0.001322 seconds.
Elapsed time is 0.000582 seconds.
ans =
1
Azzi Abdelmalek
Azzi Abdelmalek 2013 年 3 月 25 日
編集済み: Azzi Abdelmalek 2013 年 3 月 25 日
Exact, I was wondering what was wrong.

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

カテゴリ

Help Center および File ExchangeMatrix Indexing についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by