首页 > 解决方案 > 如何在未在参数中矢量化的自定义函数中使用 lapply 函数而不是 for 循环

问题描述

首先,让我们生成如下数据:

library(data.table)
data <- data.table(date = as.Date("2015-05-01")+0:299)
set.seed(123)
data[,":="(
   a = round(30*cumprod(1+rnorm(300,0.001,0.05)),2),
   b = rbinom(300,5000,0.8)
 )]

然后我想使用我的自定义函数多次操作多个列而不需要手动输入。比如我的自定义函数是add <- function(x,n) (x+n)

我提供我的 for 循环代码如下:

add <- function(x,n) (x+n)
n <- 3
freture_old <- c("a","b")
for(i in 1:n ){
  data[,(paste0(freture_old,"_",i)) := add(.SD,i),.SDcols =freture_old ]
}

你能告诉我一个lapply版本而不是 for 循环吗?

标签: rdata.table

解决方案


如果你想要的只是使用lapply循环而不是 for 循环,那么你真的不需要做太多的改变。对于一个data.table对象来说更容易,因为每次迭代都会改变它,data.table而不必将副本保存到全局环境中。我添加的一件事只是为了抑制向控制台的输出,就是将它包裹invisible起来。

lapply(1:n,function(i) data[,paste0(freture_old,"_",i):=lapply(.SD,add,i),.SDcols =freture_old])

请注意,如果您将此 lapply 分配给一个对象,您将获得data.tables迭代次数的大小列表,在本例中为 3。这将占用内存,因为您实际上只对最终条目感兴趣。因此,只需运行代码而不将其分配给变量。现在,如果您不将它分配给任何东西,您将每次迭代都打印到控制台。所以我建议invisible像这样环绕它:

invisible(lapply(1:n,function(i) data[,paste0(freture_old,"_",i):=lapply(.SD,add,i),.SDcols =freture_old]))

希望这会有所帮助,如果您需要我在此答案中添加任何其他内容,请告诉我。祝你好运!


推荐阅读