r - rbind data.frames 与不同列的有效方法

标签 r data.table rbind

我有一个包含不同列集的数据框列表。我想将它们按行组合成一个数据框。我用 plyr::rbind.fill要做到这一点。我正在寻找可以更有效地做到这一点的东西,但类似于给出的答案 here

require(plyr)

set.seed(45)
sample.fun <- function() {
   nam <- sample(LETTERS, sample(5:15))
   val <- data.frame(matrix(sample(letters, length(nam)*10,replace=TRUE),nrow=10))
   setNames(val, nam)  
}
ll <- replicate(1e4, sample.fun())
rbind.fill(ll)

最佳答案

更新:this updated answer反而。
更新(eddi):现在已在 version 1.8.11 中实现。作为 fill rbind 的参数.例如:

DT1 = data.table(a = 1:2, b = 1:2)
DT2 = data.table(a = 3:4, c = 1:2)

rbind(DT1, DT2, fill = TRUE)
#   a  b  c
#1: 1  1 NA
#2: 2  2 NA
#3: 3 NA  1
#4: 4 NA  2

FR #4790现在添加 - rbind.fill(来自 plyr),类似于合并 data.frames/data.tables 列表的功能
注1:
此解决方案使用 data.tablerbindlist用于“rbind”data.tables 列表的函数,为此,请务必使用 1.8.9 版本,因为 this bug在版本 < 1.8.9 .
笔记2:rbindlist当绑定(bind) data.frames/data.tables 列表时,截至目前,将保留第一列的数据类型。也就是说,如果第一个 data.frame 中的列是字符,并且第二个 data.frame 中的同一列是“因子”,那么 rbindlist将导致该列成为一个字符。因此,如果您的 data.frame 包含所有字符列,那么您使用此方法的解决方案将与 plyr 方法相同。如果不是,则值仍然相同,但某些列将是字符而不是因子。之后您必须自己转换为“因素”。 Hopefully this behaviour will change in the future .
现在这里使用 data.table (以及与 rbind.fill 的基准比较 plyr ):
require(data.table)
rbind.fill.DT <- function(ll) {
    # changed sapply to lapply to return a list always
    all.names <- lapply(ll, names)
    unq.names <- unique(unlist(all.names))
    ll.m <- rbindlist(lapply(seq_along(ll), function(x) {
        tt <- ll[[x]]
        setattr(tt, 'class', c('data.table', 'data.frame'))
        data.table:::settruelength(tt, 0L)
        invisible(alloc.col(tt))
        tt[, c(unq.names[!unq.names %chin% all.names[[x]]]) := NA_character_]
        setcolorder(tt, unq.names)
    }))
}

rbind.fill.PLYR <- function(ll) {
    rbind.fill(ll)
}

require(microbenchmark)
microbenchmark(t1 <- rbind.fill.DT(ll), t2 <- rbind.fill.PLYR(ll), times=10)
# Unit: seconds
#                      expr      min        lq    median        uq       max neval
#   t1 <- rbind.fill.DT(ll)  10.8943  11.02312  11.26374  11.34757  11.51488    10
# t2 <- rbind.fill.PLYR(ll) 121.9868 134.52107 136.41375 184.18071 347.74724    10


# for comparison change t2 to data.table
setattr(t2, 'class', c('data.table', 'data.frame'))
data.table:::settruelength(t2, 0L)
invisible(alloc.col(t2))
setcolorder(t2, unique(unlist(sapply(ll, names))))

identical(t1, t2) # [1] TRUE
需要注意的是plyrrbind.fill超越这个特殊的data.table解决方案,直到列表大小约为 500。
基准图:
这是带有 seq(1000, 10000, by=1000) 的 data.frames 列表长度的运行图.我用过microbenchmark在每个不同的列表长度上重复 10 次。
enter image description here
基准测试要点:
Here's the gist for benchmarking ,以防有人想要复制结果。

关于r - rbind data.frames 与不同列的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18003717/

相关文章:

rbind 输出格式到可发布表

R rbind - 参数列数不匹配

r - R 中的双 y 轴图

r - 如果前一行具有相同的值/字符串,则删除行(对于每组)

r - 按组计算第二高累积值

r - 如何在 R 中按组顺序标记类别?

r - 变量所有先验值的数学函数(例如,sd),按组

r - R 决策树

r - R中data.table中的条件字符串拆分

R函数根据重复时间组合行