【问题标题】:Out of memory when modifying a big R data.frame修改大 R data.frame 时内存不足
【发布时间】:2012-03-19 11:16:50
【问题描述】:

我有一个大约 900MB 内存的大数据框。然后我尝试像这样修改它:

dataframe[[17]][37544]=0 

似乎使 R 使用超过 3G 的内存并且 R 抱怨“错误:无法分配大小为 3.0 Mb 的向量”,(我在 32 位机器上。)

我发现这种方式更好:

dataframe[37544, 17]=0

但 R 的占用空间仍然增加了一倍,并且该命令需要相当长的时间才能运行。

从 C/C++ 背景来看,我对这种行为感到非常困惑。我认为像dataframe[37544, 17]=0 这样的事情应该在不消耗任何额外内存的情况下瞬间完成(应该只修改一个单元格)。 R 对我发布的那些命令做了什么?那么在不使内存占用加倍的情况下修改数据框中的某些元素的正确方法是什么?

非常感谢您的帮助!

【问题讨论】:

  • (Base) R 在处理大型数据结构方面并不出名。您需要研究 ffbigmemorydata.table 包的某种组合。
  • 这不是真的 - data.frames 以低效着称,但如果您关心效率,则应该使用(基础)R 中非常有效的结构。
  • @SimonUrbanek 是的,我的措辞很糟糕。我的意思正是你所说的,数据框往往效率低下,而且我提到的包通常对处理大数据的人有用。
  • @Simon 喜欢什么? matrix 仅限于普通列类型,不能像 data.frame 一样大。你是在建议list 吗?

标签: r dataframe


【解决方案1】:

跟进 Joran 建议 data.table,这里有一些链接。您的对象(大小为 900MB)即使在 32 位 R 中也可以在 RAM 中进行管理,根本不需要任何副本。

When should I use the := operator in data.table?

Why has data.table defined := rather than overloading <-?

另外,data.table v1.8.0(还没有在 CRAN 上,但在 R-Forge 上稳定)有一个 set() 函数,它可以更快地分配给元素,就像分配给 matrix 一样快(适合在内部使用例如循环)。有关更多详细信息和示例,请参阅latest NEWS。另见?":=" 链接自?data.table

还有,这是 Stack Overflow 上的 12 questions,其 data.table 标记包含单词“reference”。

为了完整性:

require(data.table)
DT = as.data.table(dataframe)
# say column name 17 is 'Q' (i.e. LETTERS[17])
# then any of the following :

DT[37544, Q:=0]                # using column name (often preferred)

DT[37544, 17:=0, with=FALSE]   # using column number

col = "Q"
DT[37544, col:=0, with=FALSE]  # variable holding name

col = 17
DT[37544, col:=0, with=FALSE]  # variable holding number

set(DT,37544L,17L,0)           # using set(i,j,value) in v1.8.0
set(DT,37544L,"Q",0)

但是,请查看链接的问题和包的文档,以了解:= 比这个简单示例更通用;例如,在 i 连接中将 := 与二分搜索结合起来。

【讨论】:

    【解决方案2】:

    在与内存相关的 R 讨论的上下文中查找“写时复制”。只要(可能非常大)数据结构的一部分发生更改,就会制作一份副本。

    一个有用的经验法则是,如果您的最大对象是 N mb/gb/... 大,则您需要大约 3*N 的 RAM。这就是带有解释系统的生活。

    几年前,当我不得不在(相对于数据量)相对低内存 32 位机器的机器上处理大量数据时,我很好地利用了 bigmemory 包的早期版本。它使用“外部指针”接口将大量内存保留在 R 之外。这不仅为您节省了“3x”因素,而且可能更多,因为您可能会摆脱不连续的内存(这是 R 喜欢的另一件事)。

    【讨论】:

    • 非常感谢!我探索了答案中提到的几个选项。我发现 bigmemory 对你来说很容易,对我来说已经足够了。
    • @agmao 或者您可以尝试:= in data.table,这正是您想要的。
    【解决方案3】:

    数据框是您可以选择对其进行修改的最糟糕的结构。由于在纯 R 代码中完成的所有功能(例如保持行名称同步、部分匹配等)的处理非常复杂(与大多数其他可以直接转到 C 的对象不同),它们倾向于强制额外的副本作为你不能就地编辑它们。检查 R-devel 对此的详细讨论 - 已多次详细讨论。

    实际规则是永远不要将数据帧用于大数据,除非您将它们视为只读。如果您处理向量或矩阵,您的效率将提高几个数量级。

    【讨论】:

      【解决方案4】:

      ff 包中有一种称为ffdf 的对象,它基本上是存储在磁盘上的data.frame。除了上面的其他提示,您还可以尝试一下。

      你也可以试试RSQLite 包。

      【讨论】:

        猜你喜欢
        • 2017-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-02
        • 2021-08-11
        • 2013-04-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多