通过附加到新环境来检查.rdata文件的内容 - 可能吗?

时间:2011-07-01 16:15:07

标签: r

我感兴趣的是列出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>

我目前通过将所有内容加载到临时环境中来解决此问题,然后复制出所需内容,但效率很低。

4 个答案:

答案 0 :(得分:19)

由于刚引用了这个问题,让我们澄清两件事:

  1. attach()只是致电load(),因此使用它而不是load

  2. 毫无意义
  3. 如果您想要选择性访问以防止屏蔽,只需将文件加载到新环境中就容易得多:

    e = local({load("foo.RData"); environment()})
    

    然后,您可以使用ls(e)并访问e$x等内容。如果你真的想在搜索路径上使用,你仍然可以在环境中使用attach

  4. 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()来避免命名冲突的风险。加载到子环境可以避免命名冲突,但不会避免加载不必要的对象。

<@>约书亚的回答远比我的绕道道路简单得多。