单件读取CSV文件的策略?

时间:2012-02-19 20:24:08

标签: r bigdata

我的计算机上有一个中等大小的文件(4GB CSV),没有足够的RAM来读取它(64位Windows上为8GB)。在过去,我只是将它加载到一个集群节点上并将其读入,但我的新集群似乎任意将进程限制为4GB的RAM(尽管硬件每台机器有16GB),所以我需要一个短期修复

有没有办法将部分CSV文件读入R以适应可用的内存限制?这样我一次可以读取文件的三分之一,将其子集化为我需要的行和列,然后在下一个文件中读取?

感谢评论者指出我可能会使用一些大内存技巧读取整个文件: Quickly reading very large tables as dataframes in R

我可以想到其他一些解决方法(例如在一个好的文本编辑器中打开,删掉2/3的观察结果,然后加载R),但如果可能的话我宁愿避免使用它们。

因此,阅读它看起来仍然是现在最好的方法。

2 个答案:

答案 0 :(得分:23)

我知道这是一个非常古老的主题。不过我最近碰到过它,因为我遇到了类似的问题。在超过这个线程后,我注意到没有提到这个问题的显着解决方案。使用连接!

1)打开与文件的连接

con = file("file.csv", "r")

2)使用read.csv

读入代码块
read.csv(con, nrows="CHUNK SIZE",...)

旁注:定义colClasses会大大加快速度。确保将不需要的列定义为NULL。

3)做你需要做的事情

4)重复。

5)关闭连接

close(con)

这种方法的优点是连接。如果省略此步骤,可能会减慢一些速度。通过手动打开连接,您基本上打开数据集,并且在调用close函数之前不要关闭它。这意味着当您遍历数据集时,您将永远不会失去您的位置。想象一下,你有一个1e7行的数据集。还想象一下,你想要一次加载一行1e5行。由于我们打开连接,我们通过运行read.csv(con, nrow=1e5,...)得到第一个1e5行,然后得到第二个块我们也运行read.csv(con, nrow=1e5,...),依此类推....

如果我们没有使用连接,我们将以相同的方式获得第一个块read.csv("file.csv", nrow=1e5,...),但是对于下一个块,我们需要read.csv("file.csv", skip = 1e5, nrow=2e5,...)。显然这是低效的。我们必须再次找到1e5 + 1行,尽管我们只读了1e5行。

最后,data.table::fread很棒。但你不能通过它连接。所以这种方法不起作用。

我希望这有助于某人。

<强>更新

人们继续赞同这篇文章,所以我想我会再加上一个简短的想法。新readr::read_csvread.csv一样,可以传递连接。但是,advertised大约快了10倍。

答案 1 :(得分:11)

您可以使用RSQLite将其读入数据库,然后使用sql语句获取一部分。

如果只需要一个部分,那么sqldf包中的read.csv.sql会将数据读入sqlite数据库。首先,它为您创建数据库,并且数据不通过R,因此R的限制将不适用(在这种情况下主要是RAM)。其次,在将数据加载到数据库之后,sqldf将指定的sql语句的输出读入R并最终销毁数据库。根据它对数据的处理速度,如果你有几个,你可能只需重复每个部分的整个过程。

只有一行代码完成了所有三个步骤,因此只需尝试就可以轻松完成。

DF <- read.csv.sql("myfile.csv", sql=..., ...other args...)

请参阅?read.csv.sql?sqldf以及sqldf home page