我在计算机上有一个中等大小的文件(4GB CSV),没有足够的RAM来读取它(在64位Windows上为8GB).在过去,我只是将它加载到一个集群节点上并将其读入,但我的新集群似乎任意将进程限制为4GB的RAM(尽管硬件每台机器有16GB),所以我需要一个短期修复.
有没有办法将CSV文件的一部分读入R以适应可用的内存限制?这样我一次可以读取文件的三分之一,将其子集化为我需要的行和列,然后在下一个三分之一读取?
感谢评论者指出我可以使用一些大内存技巧读取整个文件: 快速读取非常大的表作为R中的数据帧
我可以想到其他一些解决方法(例如在一个好的文本编辑器中打开,删掉2/3的观察结果,然后加载R),但是如果可能的话我宁愿避免使用它们.
因此,阅读它看起来仍然是现在最好的方法.
Jac*_*b H 26
我知道这是一个非常古老的主题.不过我最近遇到过它,因为我遇到了类似的问题.在超过这个线程后,我注意到没有提到这个问题的显着解决方案.使用连接!
1)打开与文件的连接
con = file("file.csv", "r")
Run Code Online (Sandbox Code Playgroud)
2)使用read.csv读取代码块
read.csv(con, nrows="CHUNK SIZE",...)
Run Code Online (Sandbox Code Playgroud)
附注:定义colClasses将大大加快速度.确保将不需要的列定义为NULL.
3)做你需要做的事
4)重复.
5)关闭连接
close(con)
Run Code Online (Sandbox Code Playgroud)
这种方法的优点是连接.如果省略此步骤,可能会减慢一些速度.通过手动打开连接,您基本上打开数据集,并且在调用close函数之前不要关闭它.这意味着当您遍历数据集时,您将永远不会失去您的位置.想象一下,你有一个1e7行的数据集.还想象一下,你想要一次加载一行1e5行.由于我们打开连接,我们通过运行得到第一个1e5行read.csv(con, nrow=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很棒.但你不能通过它连接.所以这种方法不起作用.
我希望这可以帮助别人.
UPDATE
人们继续赞同这篇文章,所以我想我会再添加一个简短的想法.新的readr::read_csv,read.csv可以通过连接.然而,它被宣传为大约快10倍.
G. *_*eck 11
您可以使用RSQLite将其读入数据库,然后使用sql语句获取一部分.
如果只需要一个部分,那么read.csv.sql在sqldf包中将数据读入sqlite数据库.首先,它为您创建数据库,并且数据不通过R,因此R的限制将不适用(在这种情况下主要是RAM).其次,在将数据加载到数据库之后,sqldf将指定的sql语句的输出读入R并最终销毁数据库.根据它对数据的处理速度,如果你有几个,你可能只需重复每个部分的整个过程.
只有一行代码完成了所有三个步骤,因此只需尝试它就可以了.
DF <- read.csv.sql("myfile.csv", sql=..., ...other args...)
Run Code Online (Sandbox Code Playgroud)
请参阅?read.csv.sql和?sqldf 以及sqldf主页.