我有一个包含不同列集的数据框列表。我想将它们按行组合成一个数据框。我用 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.table
的rbindlist
用于“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
需要注意的是plyr
的rbind.fill
超越这个特殊的data.table
解决方案,直到列表大小约为 500。基准图:
这是带有
seq(1000, 10000, by=1000)
的 data.frames 列表长度的运行图.我用过microbenchmark
在每个不同的列表长度上重复 10 次。基准测试要点:
Here's the gist for benchmarking ,以防有人想要复制结果。
关于r - rbind data.frames 与不同列的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18003717/