根据尚不存在的列创建新列

时间:2018-06-05 12:13:47

标签: r data.table

我有以下数据集:

DT <- fread("   df1 df2
  1   8
  2   9
  3  10
  4  11
  5  12")

我想创建一个新列df3,其中第一个值等于100,然后是lag(df3, 1) * (1 + df2)。所以最终的输出将是:

df1 df2     df3
1  1  8     100
2  2  9    1000
3  3 10   11000
4  4 11  132000
5  5 12 1716000

我已尝试运行DT[,df3 := lag(df3, 1) * (1 + df2)],但因为df3尚不存在,所以我收到错误。

2 个答案:

答案 0 :(得分:8)

我之前的回答是因为它取得了一些成功,但我忽略了cumprod会更快:

DT$df3 <-  100 * cumprod(c(0,DT$df2[-1])+1)        # base R
DT[, df3:= 100 * cumprod(c(0,df2[-1])+1)]          # data.table
DT %>% mutate(df3 = 100 * cumprod(c(0,df2[-1])+1)) # tidyverse (only dplyr here)

我们计算df2+1的累积积,忽略第一个元素,从1开始,然后将其乘以100

以前的回答Reduce

Reduce这是一个很好的工作,我们使用的功能是简单的乘法,然后我们确保:

  • 1添加到df2并忽略第一个值。
  • 累积结果(accumulate = TRUE

代码:

DT$df3 <- Reduce(`*`,DT$df2[-1]+1,init = 100,accumulate = TRUE)
DT
#    df1 df2     df3
# 1:   1   8     100
# 2:   2   9    1000
# 3:   3  10   11000
# 4:   4  11  132000
# 5:   5  12 1716000

这适用于基础R,可以使用data.table更多惯用语法,可以关注@ jogo的建议并撰写:

DT[, df3:=Reduce('*', df2[-1]+1, init = 100,accumulate = TRUE)]

为了完整起见,这将是tidyverse方式:

library(tidyverse)
DT %>% mutate(df3 = accumulate(df2[-1]+1,`*`,.init = 100))

答案 1 :(得分:5)

这是一种C ++方法:

library(data.table)
library(Rcpp)
cppFunction(
  'NumericVector fun(const NumericVector x, const double y) {
     const double n = x.size();

     NumericVector res = NumericVector(n);
     res[0] = y;
     for (double i = 1; i < n; i++) {
       res[i] = res[i-1] * (x[i] + 1);
     }
     return res;
   }')

DT <- fread("   df1 df2
  1   8
  2   9
  3  10
  4  11
  5  12")

DT[, df3 := fun(df2, 100)]
# > DT
#    df1 df2     df3
# 1:   1   8     100
# 2:   2   9    1000
# 3:   3  10   11000
# 4:   4  11  132000
# 5:   5  12 1716000

评论:我还在学习C ++。此功能基于Roland编写的另一个C++ function