R工作区和磁盘存储相同对象的内存差异

3

我找不到任何关于这个问题的信息,也不确定我能用哪些关键词搜索,如果这是重复内容,请见谅。

我在我的工作区中有一些数据表列表,如下所示:

> lsos()   
                       Type     Size PrettySize Rows Columns
all_subsets            list 46673512    44.5 Mb    3      NA
glm_Macro.part_1       list 15817064    15.1 Mb    2      NA
glm_Macro.part_2       list 15817064    15.1 Mb    2      NA
glm_Macro.part_3       list 15289864    14.6 Mb    2      NA

接下来我需要把列表中的最后三个项目保存在磁盘上。我只需使用save()函数和.rda扩展名就可以完成,例如:

save(glm_Macro.part_1, file = "glm_Macro.part_1.rda")

然而,在磁盘上查看,这三个文件的大小分别为270.7、268.8和262.6 MB。这是原来的约18倍。

这是有已知原因的吗?

我唯一的猜测是data.table使用引用的方式,这意味着数据不会被复制,而只是从原始数据集中引用。在这里可以看到这种方式的示例。所以当我将数据保存到磁盘时,也许它会强制复制所有的数据表,而在R工作区内部进行引用已经足够了。

终端、Rstudio和ESS(Emacs)在工作空间中显示相同的大小,所以似乎与环境无关。


1
lsos() 函数是什么意思?为什么“Columns”列是NA?为什么“Type”列是list而不是data.table?看起来第2和第3行是非常小的表格,所以要达到44Mb的大小,是否有大量的列? - Matt Dowle
哦,这些都是data.table列表。请阅读Support,并简化您的示例,即使它更加简洁。在这种情况下,选择其中一个data.table,保存它,并比较大小,然后首先报告它。 - Matt Dowle
@Matt Dowle - lsos()是multilevelPSA包中的一个函数,比仅使用ls()来检查工作区变量更有帮助。 - n1k31t4
好的,我会调查一下并回复您。顺便问一下,您以前遇到过类似的情况吗? - n1k31t4
以前从未见过18倍的扩展。请提供单个表格示例。在这种情况下,您不需要使其完全可重现(一个小示例可能不会出现问题)。使用str(DT)提供列类型对于入门者来说是可以的。 - Matt Dowle
1个回答

0

我认为这与data.table无关,而是与基本的R有关。这会导致在某些情况下glm对象的保存文件变得很大/巨大。

从您模型的名称来看,我猜测您正在函数调用内拟合glm模型。由于glm的输出包含在函数环境中创建的公式,并且公式捕获环境,因此您保存的文件将包含该函数环境。

比较:

library(multilevelPSA)

test_in_env <- function(){
  bloat <- rnorm(10000000)

  clotting <- data.frame(
    u = c(5,10,15,20,30,40,60,80,100),
    lot1 = c(118,58,42,35,27,25,21,19,18),
    lot2 = c(69,35,26,21,18,16,13,12,12))
  glm(lot1 ~ log(u), data = clotting, family = Gamma)
}

test.glm <- test_in_env()
lsos()
# Type  Size PrettySize Rows Columns
# test.glm         glm 94936    92.7 Kb   30      NA
# test_in_env function 12008    11.7 Kb   NA      NA
# GCtorture    logical    48   48 bytes    1      NA


save(test.glm, file = "glm_env_local.Rda")
# 75 Mb file created

该函数捕获本地环境,包括保存文件中的膨胀向量。 在全局情况下,没有这个函数:

bloat <- rnorm(10000000)

clotting <- data.frame(
  u = c(5,10,15,20,30,40,60,80,100),
  lot1 = c(118,58,42,35,27,25,21,19,18),
  lot2 = c(69,35,26,21,18,16,13,12,12))
test.glm <- glm(lot1 ~ log(u), data = clotting, family = Gamma)

lsos()
# bloat                numeric 80000040    76.3 Mb 1e+07      NA
# test.glm                 glm    94936    92.7 Kb 3e+01      NA
# test_in_env         function    12008    11.7 Kb    NA      NA
# clotting          data.frame     1280     1.2 Kb 9e+00       3
# local.env.formula    formula      880  880 bytes 3e+00      NA
# GCtorture            logical       48   48 bytes 1e+00      NA

save(test.glm, file = "glm_env_global.Rda")
## 5 Kb file

保存不会包括封闭环境并反映lsos的大小。 可以删除glm输出中的引用以及该对象中的其他膨胀。

有关环境的相关问题,请参见此处。 有关封装函数环境的说明,请参见Hadley Wickham的描述


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