以R表示的贴现累计金额

以R表示的贴现累计金额,r,data.table,cumulative-sum,R,Data.table,Cumulative Sum,我试图计算一个贴现的累积值,其中后面的值更值钱 假设我有以下数据集: dt <- data.table( "year" = c(79,80,81,82,83), "value" = c(5,2,6,8,9)) > dt year value 1: 79 5 2: 80 2 3: 81 6 4: 82 8 5: 83 9 贴现累计金额(DC)通过以10%的年贴现率贴现之前的值来计算。因此,对于第一行和第二行,D

我试图计算一个贴现的累积值,其中后面的值更值钱

假设我有以下数据集:

 dt <- data.table( "year" = c(79,80,81,82,83), "value" = c(5,2,6,8,9))  

> dt
   year value
1:   79     5
2:   80     2
3:   81     6
4:   82     8
5:   83     9
贴现累计金额(DC)通过以10%的年贴现率贴现之前的值来计算。因此,对于第一行和第二行,DCS值由2+5*(0.9)^1给出。对于第三行,DCS为6+(0.9)^1*2+(0.9)^2*5,依此类推

形式上,贴现金额公式如下所示:


最后,如果可能,最好使用data.table解决方案。

也许您可以尝试下面的代码


方法1 使用
sum

dt[,DCS:=sapply(1:.N,function(k) sum(0.9**(k-1:k)*head(value,k)))]

方法2 使用
Reduce
from base R

dt[,Reduce(function(x,y) 0.9*x+y,as.list(value),accumulate = TRUE)]

方法3
  • 首先,您可以构造一个矩阵
    m
    ,它给出类似卷积的系数
  • 然后你就可以跑了

结果
这里还有两个选择

1) 使用
Rcpp
,然后在
数据中通过引用进行更新。表

library(Rcpp)
cppFunction("
NumericVector dcs(NumericVector x, double disc) {
    int n = x.size();
    NumericVector res(n);
    res[0] = x[0];
    for (int i=1; i<n; i++) {
        res[i] += x[i] + res[i-1]*disc;
    }
    return res;
}")
dt[, DCS := dcs(value, 0.9)]
s <- 0
dt[, dcs2 := {
       s <- value + s*0.9
       s
    }, 
    1L:nrow(dt)]

#or simply: s <- 0; dt[, dcs2 := s <- value + s*0.9, 1L:nrow(dt)]
输出:

   year value     DCS    dcs2
1:   79     5  5.0000  5.0000
2:   80     2  6.5000  6.5000
3:   81     6 11.8500 11.8500
4:   82     8 18.6650 18.6650
5:   83     9 25.7985 25.7985
   ID n  V1
1:  1 1 1.0
2:  1 2 2.9
3:  2 1 3.0
4:  2 2 6.7

编辑:回应关于分组的评论:

dt <- data.table(ID=c(1,1,2,2), value=1:4)
dt[, {
    n <- .N
    s <- 0;
    .SD[, {
        s <- value + s*0.9;
        s
      }, 
      1L:n]
  },  
  ID]

不是一个正确的答案,但只是其他答案的时间。希望这将有助于确定选择哪个选项:

加载库
库(data.table)
图书馆(Rcpp)
创建数据集
set.seed(0L)

dt你能比较一下函数的计时吗?第二种方法很神奇,我只是从另一个答案中尝试了一下,然后是我要建议的一种实现和递归data.table解决方案,在一个有一百万行的数据集上,虽然前两种方法非常慢,而且占用内存,data.table中的递归方式非常神奇。请分享第二种方法中有关data.table语法的更多信息?出于某种原因,我似乎无法在文档中甚至通过谷歌找到它:/@ira这是马特·道尔在的一篇文章。从那时起就出现了倒退,我在项目的github站点上发布了一个问题。您愿意分享时间安排吗?在一个有
10k
观测值的数据集上,我使用microbenchmark在30次迭代中得到了以下中值时间:
sapply:5945ms
在数据中递归。表:11ms
。此外,这个答案中给出的第二个选项似乎更节省内存。我还没有尝试过Rcpp方法。很抱歉,我已经用85%的折扣系数重新计算过了。编辑。
library(Rcpp)
cppFunction("
NumericVector dcs(NumericVector x, double disc) {
    int n = x.size();
    NumericVector res(n);
    res[0] = x[0];
    for (int i=1; i<n; i++) {
        res[i] += x[i] + res[i-1]*disc;
    }
    return res;
}")
dt[, DCS := dcs(value, 0.9)]
s <- 0
dt[, dcs2 := {
       s <- value + s*0.9
       s
    }, 
    1L:nrow(dt)]

#or simply: s <- 0; dt[, dcs2 := s <- value + s*0.9, 1L:nrow(dt)]
   year value     DCS    dcs2
1:   79     5  5.0000  5.0000
2:   80     2  6.5000  6.5000
3:   81     6 11.8500 11.8500
4:   82     8 18.6650 18.6650
5:   83     9 25.7985 25.7985
dt <- data.table(ID=c(1,1,2,2), value=1:4)
dt[, {
    n <- .N
    s <- 0;
    .SD[, {
        s <- value + s*0.9;
        s
      }, 
      1L:n]
  },  
  ID]
   ID n  V1
1:  1 1 1.0
2:  1 2 2.9
3:  2 1 3.0
4:  2 2 6.7
# A tibble: 5 x 13
  expression                   min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result       memory      time   gc        
  <bch:expr>                 <dbl>    <dbl>     <dbl> <bch:byt>    <dbl> <int> <dbl>      <dbl> <list>       <list>      <list> <list>    
1 app_1                   6.34     6.34         0.158    1.12GB    0.315     1     2      6.34  <df[,7] [10~ <df[,3] [5~ <bch:~ <tibble [~
2 app_2                   0.0109   0.0123      71.3    612.34KB   21.8      72    22      1.01  <df[,7] [10~ <df[,3] [2~ <bch:~ <tibble [~
3 app_3                   3.93     3.93         0.255     4.1GB    0.764     1     3      3.93  <df[,7] [10~ <df[,3] [2~ <bch:~ <tibble [~
4 dt_rcpp                 0.000308 0.000337  2681.     195.46KB    6.01   2679     6      0.999 <df[,7] [10~ <df[,3] [2~ <bch:~ <tibble [~
5 dt_recursive            0.00939  0.00972     99.2    294.52KB    6.94    100     7      1.01  <df[,7] [10~ <df[,3] [3~ <bch:~ <tibble [~
# A tibble: 3 x 13
  expression                  min  median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result        memory       time   gc        
  <bch:expr>                <dbl>   <dbl>     <dbl> <bch:byt>    <dbl> <int> <dbl>      <dbl> <list>        <list>       <list> <list>    
1 app_2                   1.52    1.52        0.659    53.5MB    6.59      1    10       1.52 <df[,5] [1,0~ <df[,3] [27~ <bch:~ <tibble [~
2 dt_rcpp                 0.00731 0.00942    89.9      15.3MB    0.899   100     1       1.11 <df[,5] [1,0~ <df[,3] [20~ <bch:~ <tibble [~
3 dt_recursive            0.902   0.905       1.10     22.9MB    1.66      2     3       1.81 <df[,5] [1,0~ <df[,3] [4,~ <bch:~ <tibble [~