Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bounded cumulative sum?

Tags:

r

How can I do a cumulative sum over a vector (like cumsum), but bounded so that the summation never goes below a lower bound or above an upper bound?

The standard cumsum function would result in the following.

foo <- c(100, -200, 400, 200)
cumsum(foo)
# [1]  100 -100  300  500

I am looking for something as efficient as the base cumsum function. I would expect the output to look like the following.

cumsum.bounded(foo, lower.bound = 0, upper.bound = 500)
# [1]  100  0  400  500

Thanks

like image 962
Nick Allen Avatar asked Jan 21 '14 15:01

Nick Allen


People also ask

What is the meaning of cumulative sum?

Cumulative sums, or running totals, are used to display the total sum of data as it grows with time (or any other series or progression). This lets you view the total contribution so far of a given measure against time.

How do you find the cumulative sum?

Explanation: the simple formula =C2+B3 changes to =C3+B4, =C4+B5, etc. Each time the new value is added to the previous running total.


2 Answers

As mentioned in the comments, Rcpp is a good way to go.

cumsumBounded.cpp:

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]                                                             
NumericVector cumsumBounded(NumericVector x, double low, double high) {
  NumericVector res(x.size());
  double acc = 0;
  for (int i=0; i < x.size(); ++i) {
    acc += x[i];
    if (acc < low)  acc = low;
    else if (acc > high)  acc = high;
    res[i] = acc;
  }
  return res;
}

Compile and use new function:

library(Rcpp)
sourceCpp(file="cumsumBounded.cpp")
foo <- c(100, -200, 400, 200)
cumsumBounded(foo, 0, 500)
# [1] 100   0 400 500
like image 117
josliber Avatar answered Sep 28 '22 18:09

josliber


I suppose this might work.

library ("Rcpp")

cumsum.bounded <- cppFunction(
    'NumericVector cumsum_bounded (NumericVector x, const double lower, const double upper) {

        double acc = 0;
        NumericVector result(x.size());

        for(int i = 0; i < x.size(); i++) {
            acc += x[i];

            if (acc < lower) acc = lower;
            if (acc > upper) acc = upper;

            result[i] = acc;
        }

        return result;
    }')
like image 24
Nick Allen Avatar answered Sep 28 '22 18:09

Nick Allen