【问题标题】:R memory efficient way to store many data frames?R内存有效的方式来存储许多数据帧?
【发布时间】:2017-01-06 00:27:54
【问题描述】:

我正在将多个文件一起读取到数据帧列表中,以便能够将函数应用于组合数据,但是当我有太多数据帧时,我遇到了内存分配问题(“错误:R 无法分配内存” )。

例如读取的数据帧数量可变,现在假设为 3 个数据帧:

x = data.frame(A=rnorm(100), B=rnorm(200))
y = data.frame(A=rnorm(30), B=rnorm(300))
z = data.frame(A=rnorm(20), B=rnorm(600))
listDF <- list(x,y,z)

错误:R 无法分配内存

我想知道这里是否有人知道例如 [ 数组或具有许多列的单个数据帧 ] 是否是一种更有效的存储和操作数据帧的方法。

数据框列表是一种非常实用的方法,因为我可以根据数据框的名称来操作数据中的许多列,在处理可变数量的数据框时这很方便。无论如何,如果有任何想法/您喜欢这样做的任何方式,请分享它们:) 谢谢!

【问题讨论】:

  • 使您正在执行的实际代码更有效地使用内存需要查看特定代码。从广义上讲,如果您达到 RAM 限制,可以 (1) 获得一台具有更多 RAM 的计算机(例如“在云中”),或者 (2) 将磁盘上的数据保存在 files/db 中,并且只提取更小的 RAM一次处理一个块。
  • 谢谢丹尼尔!我将尝试 data.table 解决方案,我不能做的矩阵,因为我的两列都有字符和数字......谢谢!!
  • 我不确定 Daniel 的链接有多相关 - 它似乎专注于将数据添加到单个数据帧而不是多个数据帧。占用内存的是你的数据框,不管是全局环境中的数据框、列表中的数据框、列表中的数据表还是全局环境等,都无所谓。数据本身就是什么正在占用内存空间。
  • 如果数据中有很多零,您可以使用稀疏矩阵。否则按照@joran 的建议去做:获取更多内存或分块分析。

标签: r memory storage data-manipulation


【解决方案1】:

您的示例并提到apply 系列函数表明数据框的结构是相同的,即它们都具有相同的列。

如果是这种情况,并且如果总数据量(所有数据帧一起)仍然适合可用 RAM,那么解决方案可能是将所有数据打包到一个大的 data.table 中一个额外的 id 列。这可以通过函数rbindlist来实现:

library(data.table)
x <- data.table(A = rnorm(100), B = rnorm(200))
y <- data.table(A = rnorm(30), B = rnorm(300))
z <- data.table(A = rnorm(20), B = rnorm(600))
dt <- rbindlist(list(x, y, z), idcol = TRUE)
dt
      .id           A           B
   1:   1 -0.10981198 -0.55483251
   2:   1 -0.09501871 -0.39602767
   3:   1  2.07894635  0.09838722
   4:   1 -2.16227936  0.04620932
   5:   1 -0.85767886 -0.02500463
  ---                            
1096:   3  1.65858606 -1.10010088
1097:   3 -0.52939876 -0.09720765
1098:   3  0.59847826  0.78347801
1099:   3  0.02024844 -0.37545346
1100:   3 -1.44481850 -0.02598364

源自各个源数据帧的行 可以通过.id 变量来区分。所有内存高效的data.table操作都可以应用于所有行、选定行(dt[.id == 1, some_function(A)])或分组(dt[, another_function(B), by = .id])。

虽然data.table 操作具有内存效率,但 RAM 可能仍然是一个限制因素。使用tables()函数监控所有创建的data.table对象的内存消耗:

tables()
     NAME  NROW NCOL MB COLS    KEY
[1,] dt   1,100    3  1 .id,A,B    
[2,] x      200    2  1 A,B        
[3,] y      300    2  1 A,B        
[4,] z      600    2  1 A,B        
Total: 4MB

并从内存中删除不再需要的对象

rm(x, y, z)
tables()
     NAME  NROW NCOL MB COLS    KEY
[1,] dt   1,100    3  1 .id,A,B    
Total: 1MB

【讨论】:

  • 您在此处报告的内存使用具有误导性,并且是仅使用小型数据表的人工制品。用x = y = z = data.table(A = rnorm(1e6), B = rnorm(1e6))试试,你会发现组合表大于不小于x、y、z之和。
  • @dww 这是正确的,因为额外的.id 列确实需要额外的内存。但这不是重点。正如您在对@Luis 的评论中指出的那样:“data.table 可以节省内存的地方是在添加、删除或修改列的操作期间,它可以在不复制的情况下完成”
  • OP 的真实数据是否实际上具有相同的结构,或者 OP 只是做了一个方便的例子,也完全不清楚。即使它们是可组合的,虽然你是正确的,使用data.table 可以在处理过程中减少内存,正如 dww 所说,将它们放入一个大 data.table 中 - 这似乎是你答案的症结 - 不会做任何可以帮助他们首先适应记忆的东西。
  • @Gregor 感谢您的 cmets。我已经修改了我的答案以强调先决条件。
【解决方案2】:

此解决方案可能并不理想,因为它不是免费的,但Revolution R Enterprise 旨在处理 R 中的大数据问题。它使用 R 中 SQL 的一些数据操作功能来更快地计算大数据。有一个学习曲线,因为它有不同的功能来处理新的数据类型,但如果你正在处理大数据,那么加速是值得的。你只需要决定学习它的时间和产品的成本是否比一些更慢、更笨拙的解决方法对你更有价值。

【讨论】:

    【解决方案3】:

    DataTables 是 R 中非常有效的数据结构,看看它们是否对您的情况有用。

    【讨论】:

    • 数据表不会比数据帧占用更少的内存。事实上,它们是数据框,但具有附加类和相关方法。 data.table 可以节省内存的地方是在添加、删除或修改列的操作期间,它可以在不复制的情况下完成
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 2019-11-04
    • 2020-04-09
    相关资源
    最近更新 更多