我有以下数据集:
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
尚不存在,所以我收到错误。
答案 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。