R:从函数输出中使用 save() 保存 list() 时的奇怪行为

标签 r

我目前在使用 R 保存列表和“子列表”时遇到一个奇怪的问题。标题可能不明确,但这是困扰我的问题:

给定一些数据(这里的数据完全是人为的,但问题不在于模型的相关性):

set.seed(1)
a0 = rnorm(10000,10,2)
b1 = rnorm(10000,10,2)
b2 = rnorm(10000,10,2)
b3 = rnorm(10000,10,2)
data = data.frame(a0,b1,b2,b3)

还有一个返回复杂对象列表的函数(假设 lm() 对象):
test = function(k){
    tt = vector('list',k)
    for(i in 1:k) tt[[i]] = lm(a0~b1+b2+b3,data = data)
    tt
}

我们的测试函数返回一个列表 lm()对象。让我们看看这个对象的大小:
ok = test(2)
object.size(ok)
> object.size(ok)
4019336 bytes 

让我们创建 ok2 ,一个完全相似的对象,但不在函数内:
ok2 = vector('list',2)
ok2[[1]] = lm(a0~b1+b2+b3,data = data)
ok2[[2]] = lm(a0~b1+b2+b3,data = data)

...并检查他的尺寸:
> object.size(ok2)
4019336 bytes

我们在这里,okok2完全一样,所以告诉我们 R。
问题,如果我们将这些对象保存在硬盘驱动器上作为 R 对象(使用 save()saveRDS() ):
save(ok,file='ok.RData')
save(ok2,file='ok2.RData')

它们在硬盘上的大小分别为:3 366 005 bytes1 678 851 bytes .okok2 大 2 倍虽然它们完全相似!

更奇怪的是,如果你保存我们对象的“子列表”,比如 ok[[1]]ok2[[1]] (对象再次完全相同):
a = ok[[1]]
a2 = ok2[[1]]
save(a,file='console/a.RData')
save(a2,file='console/a2.RData')

它们在硬盘上的大小分别为:2 523 284 bytes838 977 bytes .

两件事情 :
为什么a的大小与a2的大小不同在硬盘上?为什么ok的大小与ok2的大小不同在硬盘上?
为什么a正好是 ok 的一半尺寸 2 523 284 bytesok尺寸在 3 366 005 bytes在高清?。

我错过了什么吗?

ps:我在 Windows 7 32 位下使用 R 2.15.1、2.15.2、2.15.3、3.0.0 以及 debian 和 R 2.15.1、R 2.15.2 运行了这个测试。我每次都遇到这个问题。

编辑

感谢@ user1609452,这里有一个似乎有效的小技巧:
test2 = function(k){

    tt = vector('list',k)
    for(i in 1:k){
        tt[[i]] = lm(a0~b1+b2+b3,data = data)
        attr(tt[[i]]$terms,".Environment") = .GlobalEnv
        attr(attr(tt[[i]]$model,"terms"),".Environment") = .GlobalEnv
    }
    tt
}

公式对象带有自己的环境和很多东西。把它放在NULL或到 .GlobalEnv 并且它似乎正在工作。像 predict.lm() 这样的函数仍然有效,我们保存的对象在 HD 上有正确的大小。不知道为什么。

最佳答案

看着

> attr(ok[[1]]$terms,".Environment")
<environment: 0x9bcf3f8>
> attr(ok2[[1]]$terms,".Environment")
<environment: R_GlobalEnv>


> ls(envir = attr(ok[[1]]$terms,".Environment"))
[1] "i"  "k"  "tt"

所以ok用它在函数的环境中拖动。

另请阅读 ?object.size
 The calculation is of the size of the object, and excludes the
 space needed to store its name in the symbol table.

 Associated space (e.g. the environment of a function and what the
 pointer in a ‘EXTPTRSXP’ points to) is not included in the
 calculation.

例如定义一个 test2和一个 ok3
test2 = function(k){
    tt = vector('list',k)
    for(i in 1:k) tt[[i]] = lm(a0~b1+b2+b3,data = data)
    rr = tt
    tt
}

ok3 <- test2(2)
save(ok3, 'ok3.RdData')

> file.info('ok3.RData')$size
[1] 5043933
> file.info('ok.RData')$size
[1] 3366005
> file.info('ok2.RData')$size
[1] 1678851

> ls(envir = attr(ok3[[1]]$terms,".Environment"))
[1] "i"  "k"  "rr" "tt"

所以ok大约是 ok2 的两倍因为它有额外的 ttok3是原来的三倍ttrr
> c(object.size(ok),object.size(ok2),object.size(ok3))
[1] 4019336 4019336 4019336

有相关讨论here

关于R:从函数输出中使用 save() 保存 list() 时的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16295507/

相关文章:

如果组中的其他行等于 1,则替换 df 中的行 [R]

r - 在R中提取带小数和空格的数字

r - ggplot2 连续直方图

r - 将价格数据聚合到 R data.table 中的不同时间范围

用 gsub 替换除某些字符串之外的字符

从 R 中的相关矩阵返回值

r - 如何对 PCoA 的散点图进行颜色编码

r - 使用二分搜索查找向量中最接近的值

c++ - 使具有依赖项的 C++ 库在 R 中可用

r - 检查 R 是否在 RStudio 中运行