使用 lapply 创建函数列表

Make list of functions with lapply

有什么方法可以使用 lapply 制作以下函数列表吗?下面,我列出了一个名为 "long" 的列表。我想使用 lapply (或 for 循环)简化代码,但似乎都不起作用。谢谢。

#This works as expected
long <- list(function(x) x <- within(x, DATE <- as.Date("2013-01-01")),
             function(x) x <- within(x, DATE <- as.Date("2014-01-01")),
             function(x) x <- within(x, DATE <- as.Date("2015-01-01")))

#This does not work
long <- lapply(2013:2015, function(i) x <- within(x, DATE <- as.Date(paste(i, "01", "01", sep = "-"))))

#This does not work
for (i in 2013:2015) long <- list(function(x) x <- within(x, DATE <- as.Date(paste(i, "01", "01", sep = "-"))))

也许最简单的方法是添加另一个 function.

long <- lapply(2013:2015,
              function(i) function(x) {
                           x <- within(x, DATE <- as.Date(paste(i, "01", "01", sep = "-")))})

检查元素是否为函数

typeof(long[[1]])
[1] "closure"

测试一下

# empty list, x
x <- list()
x <- long[[1]](x)
x
$DATE
[1] "2013-01-01"

正如@Roland 在评论中提到的那样,强制对 i 参数求值会更安全。

long <- lapply(2013:2015, function(i) {
                            force(i);
                            function(x) x <- within(x,
                                            DATE <- as.Date(paste(i, "01", "01", sep = "-")))
                           })

有一些bquote魔法:

dates <- c("2013-01-01", "2014-01-01", "2015-01-01")

lapply(dates, function(d) eval(bquote(function(x) within(x, DATE <- as.Date(.(d))))))

#[[1]]
#function (x) 
#within(x, DATE <- as.Date("2013-01-01"))
#<environment: 0x000002b1815ba450>
#
#[[2]]
#function (x) 
#within(x, DATE <- as.Date("2014-01-01"))
#<environment: 0x000002b1815ae320>
#
#[[3]]
#function (x) 
#within(x, DATE <- as.Date("2015-01-01"))
#<environment: 0x000002b1815a1520>

(赋值x <- within(...)在函数内部是多余的。)

说明:bquote 创建了一个 未计算的 表达式对象,用 .(*) 标记的符号替换了它们的值。 eval 然后计算表达式。

在这种情况下,bquote 使用 function(x) ... 创建一个生成函数的调用,并插入特定日期,因此如果 d 的值为 "2013-01-01",则bquote(function(x) ... as.Date(.(d)) 导致 未计算 表达式 function(x) ... as.Date("2013-01-01")。当你对此调用 eval 时,结果是一个包含你想要的函数体的函数对象。

有关详细信息,请参阅 ?eval?bquote