R读取一个巨大的csv
Posted
技术标签:
【中文标题】R读取一个巨大的csv【英文标题】:R reading a huge csv 【发布时间】:2016-11-26 22:26:00 【问题描述】:我有一个巨大的 csv 文件。它的大小约为 9 GB。我有 16 GB 的内存。我遵循了page 的建议并在下面实施了它们。
If you get the error that R cannot allocate a vector of length x, close out of R and add the following line to the ``Target'' field:
--max-vsize=500M
我仍然收到以下错误和警告。我应该如何将 9 GB 的文件读入我的 R?我有 R 64 位 3.3.1,并且我在 rstudio 0.99.903 中运行以下命令。我有 windows server 2012 r2 标准,64 位操作系统。
> memory.limit()
[1] 16383
> answer=read.csv("C:/Users/a-vs/results_20160291.csv")
Error: cannot allocate vector of size 500.0 Mb
In addition: There were 12 warnings (use warnings() to see them)
> warnings()
Warning messages:
1: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
2: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
3: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
4: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
5: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
6: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
7: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
8: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
9: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
10: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
11: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
12: In scan(file = file, what = what, sep = sep, quote = quote, ... :
Reached total allocation of 16383Mb: see help(memory.size)
------- 更新1
我的第一次尝试基于建议的答案
> thefile=fread("C:/Users/a-vs/results_20160291.csv", header = T)
Read 44099243 rows and 36 (of 36) columns from 9.399 GB file in 00:13:34
Warning messages:
1: In fread("C:/Users/a-vsingh/results_tendo_20160201_20160215.csv", :
Reached total allocation of 16383Mb: see help(memory.size)
2: In fread("C:/Users/a-vsingh/results_tendo_20160201_20160215.csv", :
Reached total allocation of 16383Mb: see help(memory.size)
------- 更新2
根据建议的答案,我的第二次尝试如下
thefile2 <- read.csv.ffdf(file="C:/Users/a-vs/results_20160291.csv", header=TRUE, VERBOSE=TRUE,
+ first.rows=-1, next.rows=50000, colClasses=NA)
read.table.ffdf 1..
Error: cannot allocate vector of size 125.0 Mb
In addition: There were 14 warnings (use warnings() to see them)
如何将这个文件读入单个对象,以便一次分析整个数据
-----------------更新 3
我们买了一台昂贵的机器。它有 10 个内核和 256 GB 内存。这不是最有效的解决方案,但至少在不久的将来会奏效。我看了下面的答案,但我认为它们不能解决我的问题:(我很欣赏这些答案。我想执行市场篮子分析,我认为除了将我的数据保存在 RAM 中之外别无他法
【问题讨论】:
Trimming a huge (3.5 GB) csv file to read into R的可能重复 你能指定你打算如何处理数据吗?特别是如果您的第一步是汇总它们或仅使用一些变量?ff
是一个解决方案,但相关性取决于您将做什么。另一种选择是例如结合 ff
读取然后存储在数据库中 - 您可能对 MonetDB 中的这方面感兴趣,并入 MonetDBLite
包
请告诉我们文件中的行数和列数。
@EricLecoutre 我计划探索数据。一旦我绘制并更好地理解它,我可能会删除一些行和/或列
@user1436187 36 列和 47,368,186 行...
【参考方案1】:
确保您使用的是 64 位 R,而不仅仅是 64 位 Windows,以便您可以将 RAM 分配增加到全部 16 GB。
另外,可以分块读入文件:
file_in <- file("in.csv","r")
chunk_size <- 100000 # choose the best size for you
x <- readLines(file_in, n=chunk_size)
您可以使用data.table
更有效地处理读取和操作大文件:
require(data.table)
fread("in.csv", header = T)
如果需要,您可以通过 ff
来利用存储内存:
library("ff")
x <- read.csv.ffdf(file="file.csv", header=TRUE, VERBOSE=TRUE,
first.rows=10000, next.rows=50000, colClasses=NA)
【讨论】:
我试过thefile=fread("C:/Users/a-vs/results_20160291.csv", header = T)
并收到一条消息Warning messages: 1: In fread("C:/Users/a-vs/results_20160291.csv", : Reached total allocation of 16383Mb: see help(memory.size)
我怎样才能将这个文件读入单个对象,以便我可以一次分析整个数据
@user2543622 使用ff
。但只是为了记录,将大文件分块是大数据中的标准做法。另一个答案是您可以先在 SQL 中对数据进行一些预处理。也许一旦你在 R 中得到它,你也可以将其中的一些发送到一个稀疏矩阵。【参考方案2】:
这在您的计算机上可能无法实现。在某些情况下,data.table
比 .csv
占用更多空间。
DT <- data.table(x = sample(1:2,10000000,replace = T))
write.csv(DT, "test.csv") #29 MB file
DT <- fread("test.csv", row.names = F)
object.size(DT)
> 40001072 bytes #40 MB
两个OOM大:
DT <- data.table(x = sample(1:2,1000000000,replace = T))
write.csv(DT, "test.csv") #2.92 GB file
DT <- fread("test.csv", row.names = F)
object.size(DT)
> 4000001072 bytes #4.00 GB
在 R 中存储对象存在自然开销。根据这些数字,读取文件时大约有 1.33 倍,但是,这取决于数据。例如,使用
x = sample(1:10000000,10000000,replace = T)
给出的因子大约是 2 倍 (R:csv)。
x = sample(c("foofoofoo","barbarbar"),10000000,replace = T)
给出 0.5 倍 (R:csv) 的系数。
根据最大值,您的 9GB 文件可能需要 18GB 的内存来存储在 R 中,如果不是更多的话。根据您的错误消息,您更有可能遇到硬内存限制而不是分配问题。因此,仅在夹头中读取文件并进行合并是行不通的-您还需要对分析+工作流程进行分区。另一种选择是使用 SQL 等内存工具。
【讨论】:
【参考方案3】:这将是一种可怕的做法,但根据您需要如何处理这些数据,它不应该太糟糕。您可以通过调用memory.limit(new)
来更改R 允许使用的最大内存,其中new
是一个整数,其中R 的新memory.limit
在MB 中。将会发生的情况是,当您遇到硬件限制时,Windows 将开始将内存分页到硬盘驱动器上(这不是世界上最糟糕的事情,但它会严重减慢您的处理速度)。
如果您在服务器版本上运行它,则 Windows 分页可能(很可能)与常规 Windows 10 不同。我相信它应该更快,因为服务器操作系统应该针对这些东西进行优化。
尝试从 32 GB(或 memory.limit(memory.limit()*2)
)开始,如果结果比这大得多,我会说程序最终会变得太慢它被加载到内存中。那时我会建议购买更多的 RAM 或找到一种方法来部分处理。
【讨论】:
【参考方案4】:您可能想要考虑利用一些磁盘上的处理,而不是将整个对象都放在 R 的内存中。一种选择是将数据存储在适当的数据库中,然后让 R 访问该数据库。 dplyr
能够处理远程源(它实际上是编写 SQL 语句来查询数据库)。我刚刚用一个小例子(只有 17,500 行)对此进行了测试,但希望它可以扩展到您的要求。
安装 SQLite
https://www.sqlite.org/download.html
将数据输入新的 SQLite 数据库
将以下内容保存在名为import.sql
的新文件中
CREATE TABLE tableName (COL1, COL2, COL3, COL4);
.separator ,
.import YOURDATA.csv tableName
是的,您需要自己指定列名(我相信),但如果您愿意,也可以在此处指定它们的类型。当然,如果您的姓名/数据中有逗号,这将不起作用。
通过命令行将数据导入SQLite数据库sqlite3.exe BIGDATA.sqlite3 < import.sql
将 dplyr
指向 SQLite 数据库
当我们使用 SQLite 时,所有依赖项都已由 dplyr
处理。
library(dplyr)
my_db <- src_sqlite("/PATH/TO/YOUR/DB/BIGDATA.sqlite3", create = FALSE)
my_tbl <- tbl(my_db, "tableName")
进行探索性分析
dplyr
将编写查询此数据源所需的 SQLite 命令。否则它将表现得像一个本地表。最大的例外是您无法查询行数。
my_tbl %>% group_by(COL2) %>% summarise(meanVal = mean(COL3))
#> Source: query [?? x 2]
#> Database: sqlite 3.8.6 [/PATH/TO/YOUR/DB/BIGDATA.sqlite3]
#>
#> COL2 meanVal
#> <chr> <dbl>
#> 1 1979 15.26476
#> 2 1980 16.09677
#> 3 1981 15.83936
#> 4 1982 14.47380
#> 5 1983 15.36479
【讨论】:
这是一个很好的建议!太感谢了!我一直在处理一个非常大的 csv 文件。我现在将按照您的建议尝试 sqlite。谢谢!【参考方案5】:您可以尝试在表格中拆分处理。不要对整个事情进行操作,而是将整个操作放在for
循环中,然后执行 16、32、64 次,或者您需要执行多少次。可以保存以后计算所需的任何值。这没有其他帖子那么快,但它肯定会返回。
x = number_of_rows_in_file / CHUNK_SIZE
for (i in c(from = 1, to = x, by = 1))
read.csv(con, nrows=CHUNK_SIZE,...)
希望对您有所帮助。
【讨论】:
以上是关于R读取一个巨大的csv的主要内容,如果未能解决你的问题,请参考以下文章