为啥 R 在使用 read.csv() 时会使用这么多内存?
Posted
技术标签:
【中文标题】为啥 R 在使用 read.csv() 时会使用这么多内存?【英文标题】:Why does R use so much memory when using read.csv()?为什么 R 在使用 read.csv() 时会使用这么多内存? 【发布时间】:2014-07-07 00:46:34 【问题描述】:我在 linux 上运行 R(kubuntu 值得信赖)。我有一个将近 400MB 的 csv 文件,主要包含数值:
$ ls -lah combined_df.csv
-rw-rw-r-- 1 naught101 naught101 397M Jun 10 15:25 combined_df.csv
我启动 R 和 df <- read.csv('combined_df.csv')
(我得到一个 1246536x25 数据帧、3 个 int 列、3 个 logi、1 个因子和 18 个数字),然后使用来自 here 的脚本检查内存使用情况:
R> .ls.objects()
Type Size Rows Columns
df data.frame 231.4 1246536 25
有点奇怪,它报告了 less 内存,但我猜这只是因为 CSV 不是数字数据的有效存储方法。
但是当我检查系统内存使用情况时,top
说 R 正在使用我可用的 8GB RAM 的 20%。和ps
报告类似:
$ ps aux|grep R
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
naught1+ 32364 5.6 20.4 1738664 1656184 pts/1 S+ 09:47 2:42 /usr/lib/R/bin/exec/R
1.7Gb 的 RAM 用于 379MB 的数据集。这似乎太过分了。我知道ps
isn't necessarily an accurate way of measuring memory usage,但肯定不是5倍?!为什么 R 会占用这么多内存?
此外,R 似乎在gc()
的输出中报告了类似的内容:
R> gc()
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 497414 26.6 9091084 485.6 13354239 713.2
Vcells 36995093 282.3 103130536 786.9 128783476 982.6
【问题讨论】:
当 R 从系统中获取内存时,它很少将其归还,即使它不再使用所有内存。 您是否采纳了?read.csv
中关于减少内存使用的两条建议?那里有一整节关于内存使用的明确声明:“这些函数在读取大文件时会使用惊人的内存量。”。
@JeremyS:这完全不正确,这就是垃圾收集的全部意义所在。这个问题在FAQ 7.42得到了回答。
@joran:是的! a <- read.csv('combined_df.csv', nrows=1500000, colClasses=unlist(lapply(read.csv('combined_df.csv', nrows=1), class)))
显着降低了总体内存使用量(3-4 倍)。如果您想按照这些方式发布答案,我会接受。我还将更改更改问题标题以反映问题。
gc()
并不总是像您期望的那样工作。 adv-r.had.co.nz/memory.html#gc
【参考方案1】:
正如我在上面的评论中所指出的,文档?read.csv
中有一个名为“内存使用”的部分警告说,基于read.table
的任何内容都可能使用“令人惊讶”的内存量,并建议两件事:
-
使用
colClasses
参数指定每列的类型,并且
指定nrows
,即使是“轻度高估”。
【讨论】:
另请注意FAQ 7.42。【参考方案2】:不确定您是否只是想了解 R 的工作原理,或者您是否想要 read.csv
的替代品,但请尝试 fread
from data.table
,它要快得多,而且我认为它使用的内存要少得多:
library(data.table)
dfr <- as.data.frame(fread("somecsvfile.csv"))
【讨论】:
以上是关于为啥 R 在使用 read.csv() 时会使用这么多内存?的主要内容,如果未能解决你的问题,请参考以下文章
R 中 read.csv() 和 read.csv2() 之间的区别
有没有办法使用 read.csv 从字符串值而不是 R 中的文件读取?
read.csv() 读取 data.frame OK readr::read_csv() for the same data.frame 失败,为啥?