我需要重新绑定两个大数据帧。现在我用
df <- rbind(df, df.extension)
但我(几乎)立即耗尽内存。我猜是因为df在内存中保存两次。我可能会在未来看到更大的数据帧,所以我需要某种就地rbind。
所以我的问题是:在使用rbind时,有没有办法避免内存中的数据重复?
我找到了这个使用SqlLite的question,但我真的想避免将硬盘用作缓存。
答案 0 :(得分:18)
data.table
是你的朋友!
C.f。 http://www.mail-archive.com/r-help@r-project.org/msg175877.html
跟进nikola的评论,这里是?rbindlist
的描述(v1.8.2中的新内容):
与
do.call("rbind",l)
相同,但速度更快。
答案 1 :(得分:17)
首先:如果您想要安全,请使用您链接的其他问题的解决方案。由于R是按值调用,因此忘记了不会将数据帧复制到内存中的“就地”方法。
一个不可取的方法可以节省相当多的内存,就是假装你的数据帧是列表,用for-loop强制列表(应用会吃掉像地狱一样的内存)并让R相信它实际上是一个数据帧。
我会再次警告你:在更复杂的数据帧上使用它会导致麻烦和难以发现的错误。所以一定要测试得足够好,如果可能的话,尽可能避免这种情况。
您可以尝试以下方法:
n1 <- 1000000
n2 <- 1000000
ncols <- 20
dtf1 <- as.data.frame(matrix(sample(n1*ncols), n1, ncols))
dtf2 <- as.data.frame(matrix(sample(n2*ncols), n1, ncols))
dtf <- list()
for(i in names(dtf1)){
dtf[[i]] <- c(dtf1[[i]],dtf2[[i]])
}
attr(dtf,"row.names") <- 1:(n1+n2)
attr(dtf,"class") <- "data.frame"
它会删除你实际拥有的rownames(你可以重建它们,但检查重复的rownames!)。它也没有执行rbind中包含的所有其他测试。
在我的测试中节省了大约一半的内存,在我的测试中,dtfcomb和dtf都相等。红色框是rbind,黄色框是我基于列表的方法。
测试脚本:
n1 <- 3000000
n2 <- 3000000
ncols <- 20
dtf1 <- as.data.frame(matrix(sample(n1*ncols), n1, ncols))
dtf2 <- as.data.frame(matrix(sample(n2*ncols), n1, ncols))
gc()
Sys.sleep(10)
dtfcomb <- rbind(dtf1,dtf2)
Sys.sleep(10)
gc()
Sys.sleep(10)
rm(dtfcomb)
gc()
Sys.sleep(10)
dtf <- list()
for(i in names(dtf1)){
dtf[[i]] <- c(dtf1[[i]],dtf2[[i]])
}
attr(dtf,"row.names") <- 1:(n1+n2)
attr(dtf,"class") <- "data.frame"
Sys.sleep(10)
gc()
Sys.sleep(10)
rm(dtf)
gc()
答案 2 :(得分:10)
现在我制定了以下解决方案:
nextrow = nrow(df)+1
df[nextrow:(nextrow+nrow(df.extension)-1),] = df.extension
# we need to assure unique row names
row.names(df) = 1:nrow(df)
现在我的内存不足。我认为这是因为我存储
object.size(df) + 2 * object.size(df.extension)
而rbind R需要
object.size(rbind(df,df.extension)) + object.size(df) + object.size(df.extension).
之后我使用
rm(df.extension)
gc(reset=TRUE)
释放我不再需要的记忆。
这解决了我现在的问题,但我觉得有一种更高级的方法来做一个有效的内存rbind。我感谢对此解决方案的任何评论。
答案 3 :(得分:5)
这是bigmemory
的完美候选人。有关详细信息,请参阅the site。以下是需要考虑的三个使用方面:
separated = TRUE
将列分开。我没有用过这么多,因为我的第三个提示:rbind
。注意:尽管解决数据帧和bigmemory的原始问题适用于矩阵,但是可以轻松地为不同类型的数据创建不同的矩阵,然后将这些对象组合在RAM中以创建数据帧(如果确实有必要的话)。