前面的底线:load 将数据加载到调用环境中,这在从 for 循环和从 lapply 运行时非常不同。您可以覆盖它以强制将数据加载到 哪个 环境中。
如果您阅读?load,您会看到envir= 参数:
Usage:
load(file, envir = parent.frame(), verbose = FALSE)
Arguments:
file: a (readable binary-mode) connection or a character string
giving the name of the file to load (when tilde expansion is
done).
envir: the environment where the data should be loaded.
verbose: should item names be printed during loading?
由于默认值为parent.frame(),这意味着它被加载到lapply 中定义的环境中,而不是全局环境中。
演示:
for (i in 1:2) { print(environment()); }
# <environment: R_GlobalEnv>
# <environment: R_GlobalEnv>
ign <- lapply(1:2, function(ign) print(environment()))
# [[1]]
# <environment: 0x000000006f54b838> # not R_GlobalEnv, aka .GlobalEnv
# [[2]]
# <environment: 0x000000006f54de58>
还有,因为
Value:
A character vector of the names of objects created, invisibly.
这意味着res <- lapply(files, load) 将始终只返回一个character 向量,而不是值本身。
虽然我同意 Samet Sökel 的前提,即 readRDS 提供了一个更功能 接口(意思是:它返回一些东西,它不仅仅在副作用上运行),但解决方法不是太困难:
-
加载到全局环境中:
res <- lapply(files, load, envir = .GlobalEnv)
这将返回加载到res 中的所有变量的名称,以及出现在全局环境中的所有数据。
-
加载到用户定义的环境中:
e <- new.env(parent = emptyenv())
res <- lapply(files, load, envir = e)
# all data is now in 'e'
res 也将只包含名称,但这更接近于功能接口,因为数据将进入您定义的非常具体的位置。
不要急于解决这个问题:如果您选择“生产”加载所有.rda 文件的代码,最好将数据加载到.GlobalEnv 以外的环境中。一方面,在函数内部加载并将数据放在全局中是非常糟糕的做法,并且它可能并不总是对您的函数顺利运行。好吧,它只是“一个”,生产型函数/包中的副作用是一件坏事(imo):它经常破坏可重复性,它真的会惹恼那些碰巧在 中有同名变量的用户他们的环境......覆盖它们是一种不可逆转的操作,会很快导致愤怒和生产力损失。当出现问题时,副作用也很难排除。