我感兴趣的是列出RDATA文件中的对象并仅加载选定的对象,而不是整个集合(如果有些可能很大或者可能已经存在于环境中)。当名称中存在冲突时,我不太清楚如何执行此操作,因为attach()
不能很好地工作。
1:用于检查R数据文件的内容而不加载它:这个问题与listing contents of an R data file without loading
处提出的问题类似,但不同在这种情况下,提供的解决方案是:
attach(filename)
ls(pos = 2)
detach()
如果文件中的对象与全局环境中的对象之间存在命名冲突,则会出现以下警告:
The following object(s) are masked _by_ '.GlobalEnv':
我尝试创建一个新环境,但我似乎无法附加到那个环境中。 例如,这会产生相同的错误:
lsfile <- function(filename){
tmpEnv <- new.env()
evalq(attach(filename), envir = tmpEnv)
tmpls <- ls(pos = 2)
detach()
return(tmpls)
}
lsfile(filename)
也许我用evalq
(或eval
)制造了一堆东西。还有其他方法可以避免命名冲突吗?
2:如果我想访问一个对象 - 如果没有命名冲突,我可以使用.rdat文件中的那个,或者将它复制到一个新文件。如果存在冲突,如何访问文件命名空间中的对象?
例如,如果我的文件是“sample.rdat”,并且对象是surveyData,并且在全局环境中已经存在surveyData对象,那么如何从file:sample.rdat
命名空间访问该文件呢? / p>
我目前通过将所有内容加载到临时环境中来解决此问题,然后复制出所需内容,但效率很低。
答案 0 :(得分:19)
由于刚引用了这个问题,让我们澄清两件事:
attach()
只是致电load()
,因此使用它而不是load
如果您想要选择性访问以防止屏蔽,只需将文件加载到新环境中就容易得多:
e = local({load("foo.RData"); environment()})
然后,您可以使用ls(e)
并访问e$x
等内容。如果你真的想在搜索路径上使用,你仍然可以在环境中使用attach
。
FWIW .RData文件没有索引(对象存储在一个大的pairlist中),因此您无法在不加载的情况下列出包含的对象。如果您想要方便的访问,请将其转换为延迟加载格式,而不是简单地添加索引,以便可以单独加载每个对象(请参阅Get specific object from Rdata file)
答案 1 :(得分:6)
我只使用env=
参数load()
:
> x <- 1; y <- 2; z <- "foo"
> save(x, y, z, file="/tmp/foo.RData")
> ne <- new.env()
> load(file="/tmp/foo.RData", env=ne)
> ls(env=ne)
[1] "x" "y" "z"
> ne$z
[1] "foo"
>
这种方法的成本是你确实阅读了整个RData文件---但另一方面,这似乎是不可避免的,因为没有其他方法似乎提供这样一个文件的'内容'列表。
答案 2 :(得分:4)
您可以通过在warn.conflicts=FALSE
的通话中设置attach
来取消警告。如果某个对象在全局环境中被一个对象屏蔽,您可以使用get
从附加数据中对其进行检索。
x <- 1:10
save(x, file="x.rData")
#attach("x.rData", pos=2, warn.conflicts=FALSE)
attach("x.rData", pos=2)
(x <- 1)
# [1] 1
(x <- get("x", pos=2))
# [1] 1 2 3 4 5 6 7 8 9 10
答案 3 :(得分:2)
感谢@Dirk和@Joshua。
我顿悟了。带有SMP或MC的命令/包foreach
似乎产生的环境只能继承,但似乎与全局环境不冲突。
lsfile <- function(list_files){
aggregate_ls = foreach(ix = 1:length(list_files)) %dopar% {
attach(list_files[ix])
tmpls <- ls(pos = 2)
return(tmpls)
}
return(aggregate_ls)
}
lsfile("f1.rdat")
lsfile(dir(pattern = "*rdat"))
这对我很有用,因为我现在可以将其并行化了。这是一个简单的版本,我将修改它以提供更详细的信息,但到目前为止它似乎是避免冲突的唯一方法,即使没有忽略。
因此,问题#1可以通过忽略警告(如@Joshua建议)或使用任何魔法foreach
传票来解决。
对于第2部分,加载一个对象,我认为@Joshua有正确的想法 - “得到”会做。
foreach
魔术也可以使用.noexport
选项。但是,这有风险:未经明确排除的任何内容都将从全局环境中继承/导出(我可以ls()
,但始终存在附加数据集的可能性)。为安全起见,这意味着仍必须使用get()
来避免命名冲突的风险。加载到子环境可以避免命名冲突,但不会避免加载不必要的对象。