我有一个大数据框架需要大约900MB内存。然后我试着像这样修改它:
dataframe[[17]][37544]=0
似乎让R使用超过3G ram而R抱怨“错误:无法分配大小为3.0 Mb的矢量”,(我在32位机器上。)
我发现这种方式更好:
dataframe[37544, 17]=0
但是R的足迹仍然翻了一番,命令需要相当长的时间才能运行。
从C / C ++背景来看,我对这种行为感到很困惑。我认为像dataframe[37544, 17]=0
这样的东西应该在眨眼间完成,而不需要花费任何额外的内存(只应该修改一个单元格)。 R对我发布的那些命令做了什么?在不增加内存占用量的情况下,修改数据框中某些元素的正确方法是什么?
非常感谢你的帮助!
道
答案 0 :(得分:12)
跟进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()
功能,可以更快地分配给元素,与分配给{{1}一样快}(适用于内部循环)。有关详细信息和示例,请参阅latest NEWS。另请参阅matrix
链接的?":="
。
而且,Stack Overflow上有12 questions,?data.table
标记包含“reference”一词。
为了完整性:
data.table
但是,请看一下链接的问题和软件包的文档,看看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)
如何比这个简单的例子更通用;例如,在:=
联接中将:=
与二进制搜索相结合。
答案 1 :(得分:8)
在与内存相关的R讨论的上下文中查找“copy-on-write”。只要(可能非常大的)数据结构的一部分发生变化,就会生成副本。
一个有用的经验法则是,如果你的最大物体是N mb / gb / ...大,你需要大约3 * N的RAM。这就是解释系统的生命。
多年前,当我不得不在机器上处理大量数据时(相对于数据量相对较低的ram 32位机器),我很好地利用了bigmemory软件包的早期版本。它使用“外部指针”接口将大量内存保存在R之外。这不仅可以节省'3x'因素,而且可能更多,因为你可能会使用非连续内存(这是R喜欢的另一件事) )。
答案 2 :(得分:7)
数据框是您可以选择进行修改的最差结构。由于所有功能的复杂处理(例如保持行名称同步,部分匹配等)在纯R代码中完成(与大多数其他可直接转换为C的对象不同),他们倾向于强制使用其他副本作为你无法就地编辑它们。检查R-devel对此的详细讨论 - 已经多次讨论过。
实际规则是永远不要将数据帧用于大数据,除非您将它们视为只读。如果你要处理向量或矩阵,那么你的效率会更高。
答案 3 :(得分:4)
ffdf
包中有一个名为ff
的对象类型,它基本上是存储在磁盘上的data.frame。除了上面的其他提示,你可以试试。
您还可以试用RSQLite
包。