修改大R data.frame时内存不足

agm*_*mao 11 r dataframe

我有一个大数据框架需要大约900MB内存.然后我试着像这样修改它:

dataframe[[17]][37544]=0 
Run Code Online (Sandbox Code Playgroud)

似乎让R使用超过3G ram而R抱怨"错误:无法分配大小为3.0 Mb的矢量",(我在32位机器上.)

我发现这种方式更好:

dataframe[37544, 17]=0
Run Code Online (Sandbox Code Playgroud)

但R的占地面积仍然翻了一番,命令需要相当长的时间才能运行.

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

非常感谢你的帮助!

Mat*_*wle 12

继Joran建议data.table,这里有一些链接.您的对象,900MB,即使在32位R中也可以在RAM中管理,完全没有副本.

我什么时候应该:=在data.table中使用运算符?

为什么定义data.table :=而不是重载< - ?

此外,data.tablev1.8.0(尚未在CRAN上,但在R-Forge上稳定)具有一个set()功能,可以更快地分配给元素,与分配一样快matrix(例如适合在内部循环中使用).有关详细信息和示例,请参阅最新消息.还可以看看?":="从哪个链接?data.table.

并且,这里有12个关于Stack Overflow的问题,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)
Run Code Online (Sandbox Code Playgroud)

但是,请查看链接的问题和软件包的文档,看看:=这个简单的例子是如何更通用的; 例如,:=i连接中结合二进制搜索.


Dir*_*tel 8

在与内存相关的R讨论的上下文中查找"copy-on-write".只要(可能非常大的)数据结构的一部分发生更改,就会生成副本.

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

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

  • @agmao或者你可以尝试`data.table`中的`:=`,它完全符合你的要求. (7认同)

Sim*_*nek 7

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

实际的规则是永远不要将数据帧用于大数据,除非您将它们视为只读.如果您处理向量或矩阵,那么您的效率会更高.