我有一个Rdata
包含各种对象的文件:
New.Rdata
|_ Object 1 (e.g. data.frame)
|_ Object 2 (e.g. matrix)
|_...
|_ Object n
当然我可以用 加载数据框load('New.Rdata')
,但是,有没有一种聪明的方法可以从这个文件中只加载一个特定的对象并丢弃其他对象?
.RData 文件没有索引(内容被序列化为一个大对列表)。您可以破解一种方法来遍历配对列表并仅分配您喜欢的条目,但这并不容易,因为您不能在 R 级别上做到这一点。
但是,您可以简单地将 .RData 文件转换为延迟加载数据库,该数据库分别序列化每个条目并创建索引。好消息是加载将是按需的:
# 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()
您可以指定要加载的环境一样,因此您不需要污染全局工作区等。
您可以使用attach
而不是load
将数据对象附加到搜索路径,然后您可以复制您感兴趣的一个对象并分离 .Rdata 对象。
这仍然会加载所有内容,但比将所有内容加载到全局工作区(可能会覆盖您不想覆盖的内容)然后删除您不想要的所有内容更简单。
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包可能是某些用途的替代方案。
函数可用于提取单个对象,而无需加载 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))
}
这篇博客文章提供了一种巧妙的做法,可以防止第一个问题中出现此类问题。它的要点是使用saveRDS(), loadRDS()
函数而不是常规save(), load()
函数。