Thread Subject: how can you restart CUMSUM

Subject: how can you restart CUMSUM

From: happydude

Date: 23 Nov, 2009 17:22:20

Message: 1 of 7

i have a column vector of 1's and 0's and a corresponding column of numbers I would like to cumsum. However, for each instance of there being a "1" i would like to restart a cumsum from scratch (the original vector is massive. I want to avoid doing this with loops).

How can you do this?

the sample data is a two column matrix, a vector of 1's and a vector of numbers :
x = [1,90;0,108;1,-138;0,12;1,66;1,150;1,-270;0,-24;0,24;0,0;0,-120;0,42;0,48;1,228;1,192;1,36;0,-84;0,168;];

The result I want is ths

x(:,3) = [90;NaN;-138;NaN;66;216;-54;NaN;NaN;NaN;NaN;NaN;NaN;228;420;456;NaN;NaN;]

basically NaN's whenever there is a zero and a restarted cumsum whenever there is a 1.

Finding a cumsum for the days where there are 1's is easy enough, but how to restart the cumsum from zero??

Help greatly appreciated! :)

Subject: how can you restart CUMSUM

From: Bruno Luong

Date: 23 Nov, 2009 18:41:04

Message: 2 of 7

x = [1,90;0,108;1,-138;0,12;1,66;1,150;1,-270;0,-24;0,24;0,0;0,-120;0,42;0,48;1,228;1,192;1,36;0,-84;0,168;];

% Engine
cx1=cumsum(x(:,2));
cx2=zeros(size(cx1));
i=findstr([0 x(:,1).'],[0 1]);
cx2(i)=diff([0; cx1(i)-x(i,2)]);
x3=cx1-cumsum(cx2);
x3(~x(:,1)) = NaN;

[x x3]

% Bruno

Subject: how can you restart CUMSUM

From: Matt Fig

Date: 23 Nov, 2009 20:20:18

Message: 3 of 7

Like Bruno showed, I don't see a way to both do this quickly and avoid cumsumming two times. Another alternative is to write a custom mex function, which in this case is pretty easy. Note, I am not a C guy, so this may not be the most efficient way to write the code, but it is more than twice as fast as cumsumming twice for large inputs.

MEX the function, then use it like this:
tmp = x(:,2);
tmp(~x(:,1)) = NaN;
tmp = cumsum_nan(tmp);




# include "mex.h"
# include "matrix.h"
// CUMSUM_NAN.CPP
// Speciality CUMSUM which treats NaN values as a reset to the cumsum.
void mexFunction( int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
    int row, col;
    double *INP, *OUP;
    int hh;
    row = mxGetM(prhs[0]);
    col = mxGetN(prhs[0]);
    INP = mxGetPr(prhs[0]);
    plhs[0] = mxCreateDoubleMatrix(row,col,mxREAL);
    OUP = mxGetPr(plhs[0]);
    
    for (int jj = 0; jj < col; jj++)
        *(OUP + row*jj ) = *(INP + row*jj );
    for (int ii = 1; ii<row; ii++)
    {
        for (int jj = 0; jj < col; jj++)
        {
            hh = row*jj + ii;
            if (mxIsNaN(*(INP + hh - 1)))
                *(OUP + hh) = *(INP + hh);
            else
            {
                if (mxIsNaN(*(INP + hh)))
                    *(OUP + hh) = *(INP + hh);
                else
                    *(OUP + hh) = *(OUP + hh - 1) + *(INP + hh);
            }
        }
    }
}

Subject: how can you restart CUMSUM

From: Bruno Luong

Date: 23 Nov, 2009 20:40:17

Message: 4 of 7

"Matt Fig" <spamanon@yahoo.com> wrote in message <heeqq2$ebg$1@fred.mathworks.com>...
> Like Bruno showed, I don't see a way to both do this quickly and avoid cumsumming two times. Another alternative is to write a custom mex function, which in this case is pretty easy. Note, I am not a C guy, so this may not be the most efficient way to write the code, but it is more than twice as fast as cumsumming twice for large inputs.

I'm sure you knew the answer Matt: How Matlab for-loop perform?

Bruno

Subject: how can you restart CUMSUM

From: Matt Fig

Date: 23 Nov, 2009 21:20:24

Message: 5 of 7

Funny, Bruno. I didn't even bother to check till you said something. The ML For loop performs about as fast as the mex I wrote. LOL.

Now a mex which took the whole x in and spit out the new 3 col x might be the one to beat.

Subject: how can you restart CUMSUM

From: happydude

Date: 24 Nov, 2009 15:11:20

Message: 6 of 7

thanks guys!

does the built in CUMSUM use for loops?

Subject: how can you restart CUMSUM

From: Bruno Luong

Date: 24 Nov, 2009 18:54:20

Message: 7 of 7

"happydude " <anonymousse@hotmail.com> wrote in message <hegt2o$e0h$1@fred.mathworks.com>...
> thanks guys!
>
> does the built in CUMSUM use for loops?

What else? Of course!

Bruno

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
mex Matt Fig 23 Nov, 2009 21:21:14
cumsum happydude 23 Nov, 2009 12:24:11
rssFeed for this Thread

Contact us at files@mathworks.com