Seb*_*ian 28 r dataframe rbind
我需要rbind两个大数据帧.现在我用
df <- rbind(df, df.extension)
Run Code Online (Sandbox Code Playgroud)
但我(几乎)立即失去记忆.我猜是因为df在内存中保存两次.我可能会在未来看到更大的数据帧,所以我需要某种就地rbind.
所以我的问题是:在使用rbind时,有没有办法避免内存中的数据重复?
我发现这个问题,使用SqlLite,但我真的想避免使用硬盘作为缓存.
Ari*_*man 18
data.table 是你的朋友!
比照http://www.mail-archive.com/r-help@r-project.org/msg175877.html
关注nikola的评论,这里是?rbindlist描述(v1.8.2中的新内容):
相同
do.call("rbind",l),但更快.
Jor*_*eys 17
首先:如果您想要安全,请使用您链接的其他问题的解决方案.由于R是按值调用,因此忘记了不会将数据帧复制到内存中的"就地"方法.
保存相当多内存的一种不可取的方法是假装你的数据帧是列表,使用for循环强制列表(应用会吃掉像地狱一样的内存)并让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"
Run Code Online (Sandbox Code Playgroud)
它会删除你实际拥有的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()
Run Code Online (Sandbox Code Playgroud)
Seb*_*ian 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)
Run Code Online (Sandbox Code Playgroud)
现在我的内存不足.我认为这是因为我存储
object.size(df) + 2 * object.size(df.extension)
Run Code Online (Sandbox Code Playgroud)
而rbind R则需要
object.size(rbind(df,df.extension)) + object.size(df) + object.size(df.extension).
Run Code Online (Sandbox Code Playgroud)
之后,我使用
rm(df.extension)
gc(reset=TRUE)
Run Code Online (Sandbox Code Playgroud)
释放我不再需要的记忆.
这解决了我现在的问题,但我觉得有一种更先进的方法来做一个内存有效的rbind.我感谢对此解决方案的任何评论.
这是一个完美的候选人bigmemory.有关更多信息,请访问该站点.以下是需要考虑的三个使用方面:
separated = TRUE以使列分离.我没有用过这么多,因为我的第三个提示:rbind.注意:虽然解决数据帧和bigmemory的原始问题适用于矩阵,但是可以轻松地为不同类型的数据创建不同的矩阵,然后将这些对象组合在RAM中以创建数据帧(如果确实有必要的话).
| 归档时间: |
|
| 查看次数: |
10775 次 |
| 最近记录: |