-2

I'm trying to build a more custom version of cumsum to use on a data.table, but I'm failing at the first step:

numbers <- data.table(num=1:10)

sum <- 0

cumFunct <- function(n) {
  sum <<- sum+n
  return(sum)
}

numbers[, cum:=sapply(num, cumFunct)]

While this works, it is very unclean. It also requires sum to be set to 0 before I run the function.

Now, how do I write this in a cleaner way? Essentially, how can I pass the intermediate result to the next iteration of cumFunct without using global variables?

Thanks very much!

cmaher
  • 5,100
  • 1
  • 22
  • 34
Oli
  • 317
  • 1
  • 2
  • 9
  • you probably should not ask how to do `this`, but how can I accomplish `this2`. what are you trying to calculate? – minem Apr 27 '18 at 13:55
  • The answer will probably depend on exactly how you want to customise your cumsum function; perhaps your customization could be applied to the output of cumsum, for example by `numbers[, cum:=2*cumsum(num)]` – Martin Smith Apr 27 '18 at 13:55
  • Hey - nah it will be a lot more involved. The context is calculating performance fees on a returns series, and I need to carry a few variables with me as I pass through the rows. – Oli Apr 27 '18 at 13:57
  • More specifically: I have a high-water mark figure which starts on 0 and increases row-by-row based on a specific function, and based on the level of that high water mark I need to calculate my result for a specific row. Can I achieve this without having a global variable that stores this high-water mark? I.e., can I keep passing it down as I go through the rows? – Oli Apr 27 '18 at 13:59
  • see: https://stackoverflow.com/questions/45050975/r-trailing-cumsum-per-group – Agarp Apr 27 '18 at 14:01
  • Thanks - looks like it either gets very complicated or we need more packages then! Out of interest - how does the cumsum function itself work behind the scenes (how does it store the "value so far") and why can't I replicate that in the same way? – Oli Apr 27 '18 at 15:08

2 Answers2

2

One way to do this would be to use the datatable "numbers" within the function:

numbers <- data.table(num=1:10)

cumFunct <- function(n) {
  sum <- sum(numbers[1:n])
  return(sum)
}

numbers[, cum:=sapply(num, cumFunct)]

This is not the most efficient way, but depending on what you do in your custom code, one can improve it.

Katia
  • 3,784
  • 1
  • 14
  • 27
  • Thanks - sorry, I kept my example that easy to not bore you with financial maths, but the final calculation will be a lot more complex than just summing from 1 to n :-) – Oli Apr 27 '18 at 15:07
1

An answer that is also a question: is this a pattern that will work here?

complicated.wizardry <- function(a,b){
    a+b
}

cumlist <- function(sofar, remaining, myfn){
    if(length(remaining)==1)return(c(sofar, myfn(sofar[length(sofar)],remaining[1])))
    return (  cumlist( c(sofar, myfn(sofar[length(sofar)],remaining[1])),remaining[2:length(remaining)],myfn))
    }

cumlist(0,1:10,complicated.wizardry)
steveLangsford
  • 646
  • 5
  • 9