从Rdata文件中获取特定对象

60

我有一个包含各种对象的Rdata文件:

 New.Rdata
  |_ Object 1  (e.g. data.frame)
  |_ Object 2  (e.g. matrix)
  |_...
  |_ Object n
当然我可以用 load('New.Rdata') 来加载数据框,但是有没有一种聪明的方法来仅加载文件中的一个特定对象并丢弃其他对象呢?

1
在评论中,@DWin说不行。https://dev59.com/XWw15IYBdhLWcg3wisS- - Roman Luštrik
1
但在所有事情上,我都听从Simon的意见。 - IRTFM
5个回答

78

.RData文件没有索引(内容被序列化为一个大的pairlist)。您可以通过一些hack方法遍历pairlist并仅分配所需的条目,但这并不容易,因为您无法在R级别上执行此操作。

不过,您可以将.RData文件简单地转换为lazy-load数据库,该数据库将每个条目单独序列化并创建索引。好处是加载是按需进行的:

# convert .RData -> .rdb/.rdx
e = local({load("New.RData"); environment()})
tools:::makeLazyLoadDB(e, "New")

加载数据库时,只会加载索引而不是内容。内容将在使用时加载:

lazyLoad("New")
ls()
x # if you had x in the New.RData it will be fetched now from New.rdb

就像在load()中一样,你可以指定一个环境来加载,这样就不必污染全局工作区等。


1
但是查找仍然需要通过“New.RData”进行串行访问才能获取“x”,对吗?因此,如果“x”位于“New.RData”的末尾,可能没有时间节省?问题2:在反序列化过程中遇到的其他对象会占用内存,对吗? - IRTFM
1
不,查找只是在New.rdb中寻找x的开头,并仅加载x - Simon Urbanek
11
这些功能变得更少内部的可能性有多大? - hadley
如果数据文件较大,则此方法无法正常工作。 - Reeza

19
你可以使用 attach 而不是 load,这将把数据对象附加到搜索路径上,然后您可以复制您感兴趣的一个对象并分离 .Rdata 对象。 这仍然会加载所有内容,但比将所有内容加载到全局工作区更容易处理(可能会覆盖您不想被覆盖的内容),然后再丢弃您不想要的所有内容。

14
这个答案很好,但如果有例子会更完整,因为将 .RData 对象从搜索路径中分离出来并不直观。以下是一个检索 someObjsomeFile.RData 中的示例:attach('someFile.RData'); someObj <- someObj; detach('file:someFile.RData') - C8H10N4O2
2
@C8H10N4O2,你的例子很好(而且非常明确)。但是如果你在默认位置(2)附加并在调用detach之前没有附加其他任何内容,则默认值将起作用,你只需调用detach()而不需要任何参数,它就会分离文件。这样更快更简单;你的方法更安全。 - Greg Snow

7

Simon Urbanek的回答非常好。但是它似乎无法处理需要保存的对象过大的情况:

tools:::makeLazyLoadDB(
  local({
    x <- 1:1e+09
   cat("size:", object.size(x) ,"\n")
   environment()
  }), "lazytest")
size: 4e+09 
Error: serialization is too large to store in a raw vector

我猜测这是由于当前R的实现存在限制(我使用的是2.15.2版本),而不是物理内存和交换空间用尽。然而,saves包可能是某些情况下的替代选择。


2
这更像是一条扩展注释而不是一个答案。 - C8H10N4O2

5

函数可用于从RData文件中提取单个对象,而无需加载所有内容。

extractorRData <- function(file, object) {
      #' Function for extracting an object from a .RData file created by R's save() command
      #' Inputs: RData file, object name
      E <- new.env()
      load(file=file, envir=E)
      return(get(object, envir=E, inherits=F))
    }

请在此处查看完整答案。 https://stackoverflow.com/a/65964065/4882696


0

这篇博客文章提供了一个整洁的实践方法,可以在第一个问题中防止此类问题。其要点是使用saveRDS(),loadRDS()函数而不是常规的save(),load()函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接