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

问题描述 投票:0回答:1

我应该在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()如何工作,无论在记忆或时间方面,都可以一次性读取所有数据?

r csv memory fread read.csv
1个回答
4
投票

你的问题不是fread(),它是由于没有为你的所有(205)列定义colClasses而引起的内存膨胀。但请注意,尝试将所有5.4GB读入16GB内存RAM的确是首先推动它,你几乎肯定无法将所有数据集保存在内存中;即使你可以,只要你试图处理它,你就会熄灭记忆。所以你的方法不会飞,你必须决定你可以处理哪个子集 - 你绝对需要开始哪些领域:

  • 为205列定义colClasses:整数列为'integer',双列为'numeric',布尔列为'logical',因子列为'factor'。否则事情的存储效率非常低(例如,数百万字符串非常浪费),结果很容易比原始文件大5-100倍。
  • 如果你不能适应所有7m行x205列(你几乎肯定不能),那么你需要通过执行以下部分或全部操作来积极地减少内存: 读入并处理块(行)(使用skip, nrows参数,并搜索SO以获取有关块中fread的问题) 过滤掉所有不需要的行(例如,您可以进行一些原始处理以形成您关心的子集行的行索引,然后导入更小的集合) 删除所有不需要的列(使用fread select / drop参数(指定要保留或删除的列名称的向量)。
  • 确保选项stringsAsFactors=FALSE,这是R中一个臭名昭着的错误默认值,它不会导致记忆悲伤的结束。
  • 日期/日期时间字段当前被读取为字符(这对于内存使用来说是个坏消息,数百万个唯一字符串)。要么完全删除日期列以开始,要么以块的形式读取数据并使用fasttime包或标准基本函数进行转换。
  • 看看NA治疗的方法。您可能希望暂时删除包含大量NA或乱码未处理字符串字段的列。

请参阅?freaddata.table doc以获取上述语法。如果您遇到特定错误,请发布一段代表2行数据(head(data)),您的代码和错误。

© www.soinside.com 2019 - 2024. All rights reserved.