Rolling percentage add along column

懵懂的女人 提交于 2019-12-05 23:59:55

The filter() function is part of the stats package, which is base R. Keeping to one decimal place:

round(filter(tbl$Field1, 0.1, method="recursive"), 1)

Which would produce the following results

100.0 160.0 216.0 301.6 330.2 333.0

You can use the Reduce() function as in the following.

cumpersum = function(x, percent = 0.1) {
  Reduce(function(x1, x2) percent * x1 + x2, x, accumulate = TRUE)
}

dat <- data.frame(
  Field1 = c(100, 150, 200, 280, 300, 300),
  Field2 = c(200, 180, 160, 250, 300, 250)
)

dat$Field1cumper <- cumpersum(dat$Field1, .1)
dat

#   Field1 Field2 Field1cumper
# 1    100    200        100.0
# 2    150    180        160.0
# 3    200    160        216.0
# 4    280    250        301.6
# 5    300    300        330.2
# 6    300    250        333.0

If you want to write a solution with just base R and learning programming from the very basics using a for loop and indexes, you could just know that you can write a function whose corpus look like the following:

solution= tbl$Field1
for (i in 1:length(tbl$Field1)) {

  if (i==1) {
    solution[1] = tbl$Field1[1] 
  } else {
    solution[i] = tbl$Field1[i] + pct * solution[i-1]
  }
}

though I would recommend to take a look to more advanced solutions. The lag function already mentioned could be handy.

It's tempting to figure out a solution that doesn't involve explicit looping, but I couldn't think of one. You can decompose the desired result into a sum of numbers multiplied by pct^c(0, 1, 2, ...) but I think that just makes you do a lot of extra calculation. So my solution would be simply:

fn = function(x, pct) {
  n = length(x)
  result = NA*x
  last_result = 0
  for(i in 1:n) {
    result[i] = last_result = x[i] + last_result*pct
  }
  return(result)
}

fn(tbl$Field1, 0.1)

# [1] 100.000 160.000 216.000 301.600 330.160 333.016
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!