MATLAB中索引的累计总和 [英] Cumulative sum over index in MATLAB

查看:69
本文介绍了MATLAB中索引的累计总和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下矩阵,其中第一列是索引,第二列-是值,第三列-是在索引更改后重置的累积总和:

Consider the following matrix, where the first column is the index, the second - is values, the third - is the cumulative sum which resets once the index changes:

1     1     1     % 1   
1     2     3     % 1+2
1     3     6     % 3+3
2     4     4     % 4
2     5     9     % 4+5
3     6     6     % 6
3     7    13    % 6+7
3     8    21    % 13+8
3     9    30    % 21+9
4    10    10    % 10
4    11    21    % 10+11

如何使第三列避免循环?

How can one get the third column avoiding loops?

我尝试以下操作:

  A = [1 1;...                 % Input
       1 2;...
       1 3;...
       2 4;...
       2 5;...
       3 6;...
       3 7;...
       3 8;...
       3 9;...
       4 10;...
       4 11];
  CS = cumsum(A(:,2));         % cumulative sum over the second column

  I = [diff(data(:,1));0];     % indicate the row before the index (the first column)  
                               % changes
  offset=CS.*I;                % extract the last value of cumulative sum for a given 
                               % index

  offset(end)=[]; offset=[0; offset] %roll offset 1 step forward

  [A, CS, offset]

结果是:

ans =

 1     1     1     0
 1     2     3     0
 1     3     6     0
 2     4    10     6
 2     5    15     0
 3     6    21    15
 3     7    28     0
 3     8    36     0
 3     9    45     0
 4    10    55    45
 4    11    66     0

如果有一种简单的方法可以将上面矩阵的第四列转换成

So the problem would have been solved, if there were a trivial way to transform the fourth column of the matrix above into

O =

 0
 0
 0
 6
 6
15
15
15
15
45
45

由于CS-O提供了所需的输出.

Since CS-O gives the desired output.

任何建议,我将不胜感激.

I would appreciate any suggestions.

推荐答案

使用

Use accumarray with a custom function:

result = accumarray(A(:,1), A(:,2), [], @(x) {cumsum(x)});
result = vertcat(result{:});

无论索引变化步长是否为1(如您的示例),此操作均有效.

This works irrespective of index changes being by a step of 1 (as in your example) or not.

以下方法可避免细胞,因此速度更快.在他的答案中查看@Divakar的出色基准测试(并查看他的解决方案,这是最快的):

The following approach is faster as it avoids cells. See @Divakar's excellent benchmarking in his answer (and see his solution, which is the fastest):

  1. 如果索引更改始终对应于增加1(如您的示例):

  1. If index changes always correspond to an increase by 1 (as in your example):

last = find(diff(A(:,1)))+1; %// index of last occurrence of each index value
result = A(:,2); %// this will be cumsum'd, after correcting for partial sums
correction = accumarray(A(:,1), A(:,2)); %// correction to be applied for cumsum
result(last) = result(last)-correction(1:end-1); %// apply correction
result = cumsum(result); %// compute result

  • 如果索引值更改的幅度可能大于1(即可能存在跳过"的值):这需要进行一些小的修改,从而稍微减慢速度.

  • If the index value can change by more than 1 (i.e. there may be "skipped" values): this requires a small modification that slightly slows things down.

    last = find(diff(A(:,1)))+1; %// index of last occurrence of each index value
    result = A(:,2); %// this will be cumsum'd, after correcting for partial sums
    correction = accumarray(A(:,1), A(:,2), [], @sum, NaN); %// correction
    correction = correction(~isnan(correction)); %// remove unused values
    result(last) = result(last)-correction(1:end-1); %// apply correction
    result = cumsum(result);
    

  • 这篇关于MATLAB中索引的累计总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆