通过分治策略使用`read.csv`读取巨大的csv文件吗?

时间:2019-04-14 23:29:24

标签: r csv memory fread read.csv

我应该在R中读取一个较大的csv文件(5.4GB,行数为7m,行数为205列)。我已经成功使用data.table::fread()读取了该文件。但是我想知道是否可以使用基本的read.csv()来阅读它?

我尝试仅使用暴力破解,但我的16GB RAM无法容纳该密码。然后,我尝试使用以下“分而治之”(分块)策略,但仍然无法正常工作。我该怎么办?

dt1 <- read.csv('./ss13hus.csv', header = FALSE, nrows = 721900, skip =1)
print(paste(1, 'th chunk completed'))
system.time(
  for (i in (1:9)){
    tmp = read.csv('./ss13hus.csv', header = FALSE, nrows = 721900, skip = i * 721900 + 1)
    dt1 <- rbind(dt1, tmp)
    print(paste(i + 1, 'th chunk completed'))
  }
)

我还想知道fread()是如何工作的,无论是在内存还是时间方面,它都能一次并非常有效地读取所有数据?

1 个答案:

答案 0 :(得分:3)

您的问题不是fread(),这是由于未为所有(205)列定义colClasses导致的内存膨胀。但是请注意,尝试将所有5.4GB的内容读入16GB的内存确实是将它推到了第一位,几乎可以肯定,您将无法将所有数据集都保存在内存中。即使可以,只要您尝试处理内存,都将耗尽内存。因此,您的方法不会奏效,您必须认真确定可以处理的子集-绝对需要入门的哪些领域

  • 为205列定义colClasses :'integer'代表整数列,'numeric'代表双列,'逻辑'代表布尔列,'factor'代表因子列。否则,事情将被非常低效地存储(例如,数百万个字符串非常浪费),结果很容易比原始文件大5-100倍。

  • 如果您不能容纳全部7m行x 205列(您几乎肯定不能容纳),那么您需要通过执行以下一些或所有步骤来大幅度减少内存< / strong>:

    • 读入并处理(行中的)块(使用skip, nrows参数,并在SO中搜索有关块读取的问题)
    • 过滤掉所有不需要的行(例如,您可以进行一些粗加工以形成您关心的子集行的行索引,并在以后导入小得多的行)
    • 删除所有不需要的列(使用fread select / drop自变量(指定要保留或删除的列名向量)。
  • 确保使用选项stringsAsFactors=FALSE ,这在R中是一个众所周知的糟糕默认值,不会导致内存苦恼。

  • 日期/日期时间字段当前被读取为字符(这对于内存使用和数百万个唯一字符串来说是个坏消息)。完全删除日期列以开始,或者读取数据块,然后使用fasttime包或标准基本函数对其进行转换。
  • 查看用于NA处理的参数。您现在可能要删除具有大量NA或杂乱的未处理字符串字段的列。

有关上述语法,请参见?freaddata.table doc。如果遇到特定错误,请发布一段包含两行数据(head(data)),代码和错误的代码段。