我需要rbind两个大的数据帧。现在我使用
df <- rbind(df, df.extension)但我(几乎)立即耗尽了内存。我猜这是因为df在内存中保存了两次。将来我可能会看到更大的数据帧,所以我需要一些就地的rbind。
所以我的问题是:在使用rbind时,有没有办法避免内存中的数据重复?
我找到了这个使用SqlLite的question,但我真的想避免使用硬盘作为缓存。
发布于 2011-08-18 16:43:37
现在,我想出了以下解决方案:
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。我很感谢大家对这个解决方案的评论。
发布于 2012-08-18 20:49:53
data.table是你的朋友!
C.f.http://www.mail-archive.com/r-help@r-project.org/msg175877.html
在尼古拉的评论之后,这里是?rbindlist的描述(v1.8.2中的新版本):
与
do.call("rbind",l)相同,但速度更快。
发布于 2011-08-17 22:34:10
首先:如果你想安全起见,请使用你链接到的另一个问题的解决方案。因为R是按值调用的,所以忘记“就地”方法,它不会将数据帧复制到内存中。
节省大量内存的一种不可取的方法是,假设您的数据帧是列表,使用for循环强制使用列表(应用将像地狱一样消耗内存),并使R相信它实际上是一个数据帧。
我要再次警告您:在更复杂的数据帧上使用它会自找麻烦,而且很难找到bug。因此,请确保您的测试足够好,如果可能,请尽可能避免这种情况。
您可以尝试以下方法:
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"它会删除你实际拥有的行名(你可以重建它们,但是检查重复的行名!)。它也不会执行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()https://stackoverflow.com/questions/7093984
复制相似问题