views:

65

answers:

2

This question is related to http://stackoverflow.com/questions/3101893/how-can-i-perform-this-cumulative-sum-in-matlab.

Is it possible to use TWO conditions to perform cumsum? or just one condition?

EDITED:

data = [1 22 20;...  %# Initial data
        1 22 22;...
        1 22 20;...
        1 44 11;...
        0 44 12;...
        1 33 99;...
        1 33 20;...
        1 33 50];

I want to find cumulative sum which fulfilled 2 conditions:

% 1) current row in column 1 = 1 && previous row in column 1==1;
% 2) current row in column 2 = previous row in column 2

data(:,4) = cumsum(data(:,3)); % Add a 4th column containing 
                               % the cumulative sum of column 3
index  = diff([0;data(:,1)])> 0 && diff([0;data(:,2); 0])~= 0; 
offset = cumsum(index.*(data(:,4)-data(:,3)));  
data(:,4) = data(:,4)-offset;        
index = (data(:,1) == 0); 
data(index,4) = data(index,3) 

Intended output:

data = [1 22 20 20   >> 20 + 0
        1 22 20 40   >> 20 + 20
        1 44 11 84   >> 11 + 40
        0 44 12 12   >> 12 + 0
        1 33 99 99   >> 99 + 0
        1 33 20 119  >> 20 + 99
        0 33 50 50   >> 50 + 0

EDITED: With the code below, I got the wrong output.

index = diff([0;data(:,1)])> 0 & diff([0;data(:,2)])~=0

 1    22    20    20
 1    22    22    42
 1    22    20    62
 1    44    11    73 %this supposed to be 11 not 73 ..
 0    44    12    12
 1    33    99    99
 1    33    20   119
 1    33    50   169
A: 

I'm slow and don't yet really understand what you are trying to do. Could you describe it in words ? When you do, separate the specification of which elements of your array data you want to operate on, and the specification of the cumulative sum The Matlab function cumsum does not take any conditions, you have to write Matlab statements to select the data you want to sum first.

Your second condition data(1:end-1)==data(2:end) looks suspicious to me since they use linear indexing which is probably not what you want. If you don't understand the term linear indexing try experimenting with a few references such as data(4) and data(24), ie one-dimensional indices into a two-dimensional array.

So the statement

index = diff([0;data(:,1)])> 0 && diff([0;data(:,2); 0])~= 0;

raises errors. What you have to do here is use Matlab interactively to build up the statement you want to execute piece-bypiece. So, does

[0;data(:,1)]

produce the result you expect ? Do you understand what it produces ? Next, ask the same questions of

diff([0;data(:,1)])

and then of

diff([0;data(:,1)])> 0

and keep going. At some point you will discover that Matlab does not do what you expect -- and this is because your expectation is wrong.

Finally, one thing that is definitely wrong is that the sub-expressions diff([0;data(:,1)])> 0 and diff([0;data(:,2); 0])~= 0 produce vectors with different lengths.

EDIT: The operator & may be what you want since it will operate element-by-element on your two arrays.

EDIT 2: I'm afraid I have no more time to help you on this one, so I suggest you rewrite your program to explicitly loop over the data array building the cumulative sum as it goes.

High Performance Mark
Thank you. Actually I want to find a cumulative sum which row in column 1 = 1 and current row in column2 = previous row in column 2
Jessy
@Jessy: I don't understand your comment. Which columns do you want to sum, and which columns do you want to match ? All of them ?
High Performance Mark
sorry for the confusion. I have changed the output. column that I want to sum is the 3rd column, and I want to match column 1 and column 2. current row in column 1=current row in column 1, and current row in column 2 == previous row on column 2.
Jessy
A: 

Following your question as written (just satisfying the two conditions you have) you need an expression for index like this:

index = data(:,1) & ([0;diff(data(:,2))] == 0);

Note this only applies the cumulative sum where both of your conditions (restated below) are satisfied:

  1. rows where column 1 is 1
  2. rows where column 2 matches the previous row or is the first row

For me, this produces an output of

data(index,4) = cumsum(data(index,3))
data =

     1    22    20    20
     1    22    22    42
     1    22    20    62
     1    44    11     0
     0    44    12     0
     1    33    99     0
     1    33    20    82
     1    33    50   132

That said, this won't produce your desired output, so either your conditions or the desired output are wrong.

Mark E

related questions