加载 ffdf 数据占用大量内存

Posted

技术标签:

【中文标题】加载 ffdf 数据占用大量内存【英文标题】:Loading ffdf data take a lot of memory 【发布时间】:2012-12-19 13:53:45 【问题描述】:

我遇到了一个奇怪的问题: 我使用

保存ffdf 数据
save.ffdf()

来自ffbase 包,当我在新的 R 会话中加载它们时,做

load.ffdf("data.f") 

与 R 中的 data.frame 对象相同的数据相比,它被加载到 RAM 中大约 90% 的内存。 遇到这个问题,使用ffdf 没有多大意义,不是吗? 我不能使用ffsave,因为我在服务器上工作并且上面没有 zip 应用程序。

packageVersion(ff) # 2.2.10
packageVersion(ffbase) # 0.6.3

有什么想法吗?

[编辑]一些代码示例以帮助澄清:

data <- read.csv.ffdf(file = fn, header = T, colClasses = classes) 
# file fn is a csv database with 5 columns and 2.6 million rows,
# with some factor cols  and some integer cols. 
data.1 <- data 
save.ffdf(data.1 , dir = my.dir) # my.dir is a string pointing to the file. "C:/data/R/test.f" for example. 

关闭 R 会话...再次打开:

load.ffdf(file.name) # file.name is a string pointing to the file. 
#that gives me object data, with class(data) = ffdf. 

然后我有一个数据对象 ffdf[5] ,它的内存大小几乎和:

data.R <- data[,] # which is a data.frame. 

[编辑结束]

*[ 第二次编辑 :: 完全可重现的代码 ::: ]

由于我的问题还没有回答,我仍然发现问题,我举一个可重现的例子::

dir1 <- 'P:/Projects/RLargeData';
setwd(dir1);
library(ff)
library(ffbase)

memory.limit(size=4000)
N = 1e7; 
df <- data.frame( 
 x = c(1:N), 
 y = sample(letters, N, replace =T), 
 z = sample( as.Date(sample(c(1:2000), N, replace=T), origin="1970-01-01")),
 w = factor( sample(c(1:N/10) , N, replace=T))   )

df[1:10,]
dff <- as.ffdf(df)
head(dff)
#str(dff)

save.ffdf(dff, dir = "dframeffdf")
dim(dff)
# on disk, the directory "dframeffdf" is : 205 MB (215.706.264 bytes)

### resetting R :: fresh RStudio Session 
dir1 <- 'P:/Projects/RLargeData';
setwd(dir1);
library(ff)
library(ffbase)
memory.size() # 15.63 
load.ffdf(dir = "dframeffdf")
memory.size() # 384.42
gc()
memory.size() # 287

所以我们有 384 Mb 的内存,在 gc() 之后有 287,这大约是磁盘中数据的大小。 (也在 Windows 的“进程资源管理器”应用程序中检查)

> sessionInfo()
R version 2.15.2 (2012-10-26)
Platform: i386-w64-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=Danish_Denmark.1252  LC_CTYPE=Danish_Denmark.1252    LC_MONETARY=Danish_Denmark.1252 LC_NUMERIC=C                    LC_TIME=Danish_Denmark.1252    

attached base packages:
[1] tools     stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ffbase_0.7-1 ff_2.2-10    bit_1.1-9

[结束第二次编辑]

【问题讨论】:

您使用什么类型的数据?你能给我们看几行吗? 几行代码在这里会有所帮助。您是否尝试过 save.ffdf(yourffdf, anotherffdf)。你确定你没有在“data.f”中保存其他在 RAM 中的对象吗... 大家好,谢谢您的回答。我在问题帖子中添加(编辑)了几行代码。希望这会有所帮助。 感谢您的代码。 ffdf[5]中的内存大小和数据类型是如何获得的 获取内存的代码来自:sapply(ls(), function(x) object.size(x))。 【参考方案1】:

在 ff 中,当您有因子列时,因子水平始终在 RAM 中。 ff 字符列当前不存在,字符列被转换为 ffdf 中的因子。

关于您的示例:您在“dff”中的“w”列包含超过 6 个 Mio 级别。这些级别都在 RAM 中。如果您没有具有很多级别的列,您将不会看到 RAM 增加,如下所示,使用您的示例。

N = 1e7; 
df <- data.frame( 
 x = c(1:N), 
 y = sample(letters, N, replace =T), 
 z = sample( as.Date(sample(c(1:2000), N, replace=T), origin="1970-01-01")),
 w = sample(c(1:N/10) , N, replace=T))   
dff <- as.ffdf(df)
save.ffdf(dff, dir = "dframeffdf")

### resetting R :: fresh RStudio Session 
library(ff)
library(ffbase)
memory.size() # 14.67
load.ffdf(dir = "dframeffdf")
memory.size() # 14.78

【讨论】:

太好了,这解释了一切。谢谢你。有没有办法让数据库具有例如“xs23134”形式的 400 万个唯一“id”和 4000 万个 obs,而不是进入 RAM?也许将那些转换为整数?正如您所说,任何字符都将转换为因子,然后转换为 RAM ......关于如何处理的任何建议? 是的,将其转换为整数。请参阅 ffbase 中的 ?ikey 为您执行此操作,然后您可以删除您的因素。并考虑一下您在分析练习中是否真的需要您的字符列(我的经验是,您在数据挖掘练习中几乎不需要这些,而只是用于事后链接回您的数据库) 我明白了……是的,这是个好主意,我过去一直在应用它。问题是,在我的“编辑数据”部分编码中,我有成百上千行这样的(一般编码): if( id = "sc1234" ) .... if(diagnose like "X12WS... " 然后 ....) 等等。因此将所有因素编码为整数会导致无法“看到”您在做什么的问题......这就是我想保留字符字段的原因。编辑数据后,在分析部分,我使用从因子传递到整数,以提高速度。【参考方案2】:

ffdf 包具有在“物理”和“虚拟”存储中隔离对象的机制。我怀疑你是在物理内存中隐式构造项目,但由于你没有提供这个工作空间是如何创建的编码,所以只有这么多猜测是可能的。

【讨论】:

您好,谢谢您的回答。我在问题帖子中添加(编辑)了几行代码。希望这会有所帮助。

以上是关于加载 ffdf 数据占用大量内存的主要内容,如果未能解决你的问题,请参考以下文章

如何正确统计C程序运行的内存占用量?

PHP查询MySQL大量数据的内存占用分析

数据库占用大量内存的检测和优化(PostgreSQL)

如何使用具有超过 2^31 个观测值的 biglm

jupyter笔记本中的Plotly数据占用了大量内存

在 C# 中序列化 DataTable 会占用大量内存 - 如何改进这一点