有没有办法延迟加载列表元素?
我有一个大型数据帧列表,每个数据帧都需要很长时间才能生成和加载。通常,我不会在 session 期间使用所有 data.frames,因此希望它们在我使用它们时延迟生成和加载。我知道我可以使用delayedAssign创建延迟加载的变量,但这不能应用于列表元素。
下面是一个不起作用的可重现示例:
一些需要一段时间才能生成 data.frames 的函数:
slow_fun_1 <- function(){
cat('running slow function 1 now \n')
Sys.sleep(1)
df<-data.frame(x=1:5, y=6:10)
return(df)
}
slow_fun_2 <- function(){
cat('running slow function 2 now \n')
Sys.sleep(1)
df<-data.frame(x=11:15, y=16:20)
return(df)
}
方法 1
my_list <- list()
my_list$df_1 <-slow_fun_1()
my_list$df_2 <-slow_fun_2()
# This is too slow. I might not want to use both df_1 & df_2.
方法 2
my_list_2 <- list()
delayedAssign('my_list_2$df_1', slow_fun_1())
delayedAssign('my_list_2$df_2', slow_fun_2())
# Does not work. Can't assign to a list.
my_list_2 #output is still an empty list.
最佳答案
这是一种可能的解决方案。这不是懒惰的评估。但它会在您需要时计算 data.frame (然后将其缓存,因此仅在第一次进行计算)。您可以使用包 memoise
来实现此目的。例如
slow_fun_1 <- function(){
cat('running slow function 1 now \n')
Sys.sleep(1)
df<-data.frame(x=1:5, y=6:10)
return(df)
}
slow_fun_2 <- function(){
cat('running slow function 2 now \n')
Sys.sleep(1)
df<-data.frame(x=11:15, y=16:20)
return(df)
}
library(memoise)
my_list <- list()
my_list$df_1 <-memoise(slow_fun_1)
my_list$df_2 <-memoise(slow_fun_2)
请注意,my_list$df_1
等实际上是为您提供data.frames的函数,因此您的用法应如下所示:
> my_list$df_1()
running slow function 1 now
x y
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10
> my_list$df_1()
x y
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10
>
请注意,缓存函数仅在第一次执行实际计算。
更新:如果您想坚持原来的用法而不调用函数,一种方法是基于列表修改数据结构,例如:
library(memoise)
lazy_list <- function(...){
structure(list(...), class = c("lazy_list", "list"))
}
as.list.lazy_list <- function(x){
structure(x, class = "list")
}
generator <- function(f){
structure(memoise(f), class = c("generator", "function"))
}
`$.lazy_list` <- function(lst, name){
r <- as.list(lst)[[name]]
if (inherits(r, "generator")) {
return(r())
}
return(r)
}
`[[.lazy_list` <- function(lst, name){
r <- as.list(lst)[[name]]
if (inherits(r, "generator")) {
return(r())
}
return(r)
}
lazy1 <- lazy_list(df_1 = generator(slow_fun_1),
df_2 = generator(slow_fun_2),
df_3 = data.frame(x=11:15, y=16:20))
lazy1$df_1
lazy1$df_1
lazy1$df_2
lazy1$df_2
lazy1$df_3
关于r - R 中列表元素的惰性求值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45015916/