# Cumulative sum of consecutive positive or negative numbers

I have a huge array of positive and negative numbers. I am trying to find cumulative sum of consecutive positive and negative numbers. The cumulative sum should restart every time the sign changes.

For example, I have

data =
{-1, 2, 3, 4, 2, 1, -2, -5, 3, 1, 2, 1, -1, -1, 1, 2, 4, -1, 1, 1, -1, -2, 1};


I want:

cusum =
{-1, 2, 5, 9, 11, 12, -2, -7, 3, 4, 6, 7, -1, -2, 1, 3, 7, -1, 1, 2, -1, -3, 1};


so that the result looks like

Any help is greatly appreciated.

With data being

data = {-1, 2, 3, 4, 2, 1, -2, -5, 3, 1, 2, 1, -1, -1, 1, 2, 4, -1, 1, 1, -1, -2, 1};


as in the OP, then do

Accumulate /@ SplitBy[data, Sign] // Flatten
(* {-1, 2, 5, 9, 11, 12, -2, -7, 3, 4, 6, 7, -1, -2, 1, 3, 7, -1, 1, 2, -1, -3, 1} *)

• @ march, thank you so much. In fact, I spent almost an hour to do it without success. I am going to leave this question so that someone in the future will not waste their time. I really appreciate it. Aug 9, 2017 at 5:37

Since you mentioned you are working with huge arrays, you might consider using Compile. For instance, here are two possible Compile approaches:

fc = Compile[{{a, _Integer}, {b, _Integer}},
If[a b <= 0, b, a + b]
];

gc = Compile[{{a, _Integer, 1}},
Module[{total = 0},
Table[
If[a[[i]] total <= 0,
total = a[[i]],
total += a[[i]]
],
{i, Length[a]}
]
]
];


A comparison on a list with a million elements:

data = RandomInteger[{-5, 5}, 10^6];

r1 = gc[data]; //AbsoluteTiming
r2 = FoldList[fc, data]; //AbsoluteTiming
r3 = Accumulate /@ SplitBy[data, Sign] // Flatten; //AbsoluteTiming

r1 === r2 === r3


{0.047799, Null}

{0.072444, Null}

{1.45911, Null}

True

• @ Carl, thank you for your time and answer. It is really appreciated. Aug 9, 2017 at 13:16
Flatten[FoldList[Plus, #] & /@ Split[data, Sign[#1] == Sign[#2] &],2]

• @ Alucard, thank you for your time and answer. I really appreciate it. Aug 9, 2017 at 13:17