修剪一个巨大的(3.5 GB)CSV文件读入R

所以我有一个数据文件(分号分隔),有很多细节和不完整的行(导致访问和SQL扼杀)。 它是县级数据集,分为40个年份的细分市场,细分市场和次细分市场(总共约200个因素)。 简而言之,这是巨大的,如果我试图简单地阅读它,它就不会适应记忆。

所以我的问题是,因为我希望所有的县,但只有一年(也就是最高水平的段…最终导致约10万行),什么是最好的方法来获得这汇总到R?

目前,我正在试图用Python剔除不相关的年份,一次读取和操作一行,以避免文件大小的限制,但我更喜欢R-only解决scheme(CRAN包OK)。 有没有一种类似的方式来在R中一次读入一个文件?

任何想法将不胜感激。

更新:

  • 约束
    • 需要使用我的机器,所以没有EC2实例
    • 作为R只有尽可能。 在这种情况下,速度和资源是不是担心…提供我的机器不爆炸…
    • 如下所示,数据包含混合types,我需要稍后进行操作
  • 数据
    • 数据是3.5GB,大约有850万行和17列
    • 几千行(〜2K)是畸形的,只有一列而不是17
      • 这些都是不重要的,可以放弃
    • 我只需要大约100,000行(见下文)

数据示例:

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ... Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ... Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ... NC [Malformed row] [8.5 Mill rows] 

我想砍掉一些专栏,从40年(2009 – 2010年,从1980 – 2020年)中挑选出两个,这样数据就可以符合R:

 County; State; Year; Quarter; Segment; GDP; ... Ada County;NC;2009;4;FIRE;80.1; ... Ada County;NC;2010;1;FIRE;82.5; ... [~200,000 rows] 

结果:

在对所有build议做了修改之后,我决定由JD和Marekbuild议的readLines最好。 我给了Marek这个支票,因为他给了一个样本实施。

我已经使用strsplit和cat来保留我想要的列,马克的执行的稍微改编版本在这里我的最终答案。

还应该注意,这比Python的效率低得多,因为Python在5分钟内通过3.5GB文件咀嚼,而R大约需要60 …但是如果你拥有的是R,那么这就是票据。

 ## Open a connection separately to hold the cursor position file.in <- file('bad_data.txt', 'rt') file.out <- file('chopped_data.txt', 'wt') line <- readLines(file.in, n=1) line.split <- strsplit(line, ';') # Stitching together only the columns we want cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE) ## Use a loop to read in the rest of the lines line <- readLines(file.in, n=1) while (length(line)) { line.split <- strsplit(line, ';') if (length(line.split[[1]]) > 1) { if (line.split[[1]][3] == '2009') { cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE) } } line<- readLines(file.in, n=1) } close(file.in) close(file.out) 

按方法失败:

  • sqldf
    • 如果数据是格式良好的,那么这将是我将来用于这类问题的绝对方法。 但是,如果不是,那么SQLite扼杀。
  • MapReduce的
    • 说实话,这个文件吓了我一下,所以我没有考虑到。 看起来好像它也需要把这个东西留在记忆里,如果真是这样的话,那么这个东西就会失败。
  • bigmemory
    • 这种方法干净地链接到数据,但它一次只能处理一种types。 结果,我所有的angular色vector都放到了big.table中。 如果我需要为将来devise大型数据集,我只会考虑使用数字来保持这个选项的活跃。
  • 扫描
    • 扫描似乎有大内存类似的问题,但与readLines的所有机制。 简而言之,这次只是不适合这个法案。

我尝试readLines 。 这段代码创buildcsv与选定的年份。

 file_in <- file("in.csv","r") file_out <- file("out.csv","a") x <- readLines(file_in, n=1) writeLines(x, file_out) # copy headers B <- 300000 # depends how large is one pack while(length(x)) { ind <- grep("^[^;]*;[^;]*; 20(09|10)", x) if (length(ind)) writeLines(x[ind], file_out) x <- readLines(file_in, n=B) } close(file_in) close(file_out) 

有没有一种类似的方式来在R中一次读入一个文件?

是。 readChar()函数将读取一个字符块,而不会假定它们是以null结尾的。 如果您想一次读取一行中的数据,则可以使用readLines() 。 如果你读一个块或一行,做一个操作,然后写出数据,你可以避免内存问题。 尽pipe如果你想在亚马逊的EC2上启动一个大型的内存实例,你可以得到64GB的内存。 这应该保存你的文件,并有足够的空间来操作数据。

如果你需要更快的速度,那么Shanebuild议使用Map Reduce是一个非常好的select。 但是,如果你走在EC2上使用大内存实例的路线,你应该看看使用机器上所有内核的多核包。

如果你发现自己想读取许多到R的分隔数据,你至less应该研究一下sqldf包,它允许你从R直接导入到sqldf中,然后对R中的数据进行操作。我发现sqldf是一个如前面提到的问题所述,将最新的数据导入到R中。

我不是这方面的专家,但你可以考虑尝试MapReduce ,这基本上意味着采取“分而治之”的方法。 R有几个select,包括:

  1. mapReduce (纯R)
  2. RHIPE (使用Hadoop ); 请参阅文档中的示例6.2.2 以了解子集文件的示例

另外,R提供了几个软件包来处理大量的数据,这些数据在内存之外(在磁盘上)。 您可能可以将整个数据集加载到一个大bigmemory对象中,并在R内完全减less。请参阅http://www.bigmemory.org/以获取一组工具来处理这个问题。;

ff包是处理大文件的透明方式。

您可能会看到包装网站和/或关于它的介绍 。

我希望这有帮助

您可以将数据导入SQLite数据库 ,然后使用RSQLiteselect子集。

有一个叫做colbycol的全新软件包,可以让你只读取你想要的巨大文本文件中的variables:

http://colbycol.r-forge.r-project.org/

它将任何parameter passing给read.table,所以组合应该让你的子集非常紧密。

你有没有consmered大内存 ? 看看这个和这个 。

怎样使用readrread_*_chunked readr family?

所以在你的情况下:

testfile.csv

 County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP Ada County;NC;2009;4;FIRE;Financial;Banks;80.1 Ada County;NC;2010;1;FIRE;Financial;Banks;82.5 lol Ada County;NC;2013;1;FIRE;Financial;Banks;82.5 

实际的代码

 require(readr) f <- function(x, pos) subset(x, Year %in% c(2009, 2010)) read_csv2_chunked("testfile.csv", DataFrameCallback$new(f), chunk_size = 1) 

这将f到每个块,记住col-name并在最后组合过滤结果。 请参阅?callback ,这是本示例的来源。

这导致:

 # A tibble: 2 × 8 County State Year Quarter Segment `Sub-Segment` `Sub-Sub-Segment` GDP * <chr> <chr> <int> <int> <chr> <chr> <chr> <dbl> 1 Ada County NC 2009 4 FIRE Financial Banks 801 2 Ada County NC 2010 1 FIRE Financial Banks 825 

你甚至可以增加chunk_size但在这个例子中只有4行。

也许你可以迁移到MySQL或PostgreSQL,以防止自己的MS Access限制。

使用基于数据库连接器的DBI (可用于CRAN)连接R到这些系统是相当容易的。

scan()同时具有nlines参数和skip参数。 是否有一些原因,你可以用它来一次读大块的线,检查date,看看是否合适? 如果input文件是按datesorting的,则可以存储一个索引,告诉您应该使用什么样的跳过和nlines来加速将来的进程。

这些天,3.5GB只是不是真的那么大,我可以以2.80美元/小时的速度访问亚马逊云上的244GB内存(r3.8xlarge)的机器。 需要多less小时才能弄清楚如何使用大数据types解决scheme来解决问题? 你的时间值多less钱? 是的,它会花你一两个小时来弄清楚如何使用AWS – 但是你可以在免费的一层学习基础知识,上传数据并读取第一个10k行到R来检查它的工作,然后你可以启动一个像r3.8xlarge这样的大内存实例,全部阅读! 只是我的2C。

现在,2017年,我会build议去火花和sparkR。

  • 语法可以用一种简单而相似的方式来编写

  • 它适合小内存(2017年意义小)

不过,这可能是一个令人恐惧的经验,开始…

我会去一个数据库,然后进行一些查询,通过DBI提取您需要的样本

请避免将3.5 GB的csv文件导入到SQLite中。 或者至less仔细检查一下你的HUGE db是否符合SQLite的限制, http: //www.sqlite.org/limits.html

这是一个该死的大DB你有。 如果你需要速度,我会去找MySQL。 但要准备等待很多小时才能完成导入。 除非你有一些非常规的硬件或者你正在写未来…

亚马逊的EC2也可以是一个很好的解决scheme,用于实例化运行R和MySQL的服务器。

我的两个卑微的便士值得。