这是一个使用包的版本data.table
,对于非常大的数据来说要快一点。它使用函数rbindlist
及其fill=TRUE
传递给函数的参数do.call
。
library(data.table)
x <- list()
x[[1]] <- letters[seq(2,20,by=2)]
names(x[[1]]) <- LETTERS[c(1:length(x[[1]]))]
x[[2]] <- letters[seq(3,20, by=3)]
names(x[[2]]) <- LETTERS[seq(3,20, by=3)]
x[[3]] <- letters[seq(4,20, by=4)]
names(x[[3]]) <- LETTERS[seq(4,20, by=4)]
x2 <- lapply(x, as.list)
rbindlist(x2, fill=TRUE)
#> A B C D E F G H I J L O R P T
#> 1: b d f h j l n p r t <NA> <NA> <NA> <NA> <NA>
#> 2: <NA> <NA> c <NA> <NA> f <NA> <NA> i <NA> l o r <NA> <NA>
#> 3: <NA> <NA> <NA> d <NA> <NA> <NA> h <NA> <NA> l <NA> <NA> p t
它增加了一点开销,因为它需要将字符向量转换为as.list
. 这段话还可以增加流程的时间,具体取决于数据的生成方式。
另一方面,它似乎在大型数据集上执行得更快。
它返回一个data.table
.
我重写了@Arun 和@GSee 的示例以生成更大的样本。
数据
# generate some huge random data:
set.seed(45)
sample.fun <- function() {
nam <- sample(LETTERS, sample(5:15))
val <- sample(letters, length(nam))
setNames(val, nam)
}
l1 <- replicate(1e6, sample.fun()) # Arun's data, just bigger
l2 <- lapply(l1, as.list) # same data converted with as.list
职能
library(microbenchmark)
library(data.table)
# Arun's function
rbind.named.fill <- function(x) {
nam <- sapply(x, names)
unam <- unique(unlist(nam))
len <- sapply(x, length)
out <- vector("list", length(len))
for (i in seq_along(len)) {
out[[i]] <- unname(x[[i]])[match(unam, nam[[i]])]
}
setNames(as.data.frame(do.call(rbind, out), stringsAsFactors=FALSE), unam)
}
# GSee's function
foo <- function (...)
{
dargs <- list(...)
all.names <- unique(names(unlist(dargs)))
out <- do.call(rbind, lapply(dargs, `[`, all.names))
colnames(out) <- all.names
as.data.frame(out, stringsAsFactors=FALSE)
}
基准测试
microbenchmark(t1 <- rbind.named.fill(l1),
t2 <- rbindlist(l2, fill=TRUE),
t3 <- do.call(foo, l1),
times=10)
#> Unit: seconds
#> expr min lq mean median uq max neval
#> t1 <- rbind.named.fill(l1) 6.536782 7.545538 9.118771 9.304844 10.505814 11.28260 10
#> t2 <- rbindlist(l2, fill=TRUE) 5.250387 5.787712 6.910340 6.226065 7.579503 10.40524 10
#> t3 <- do.call(foo, l1) 9.590615 11.043557 13.504694 12.550535 15.364464 19.95877 10
identical(t1, data.frame(t2))
#> [1] TRUE
identical(t3, data.frame(t2))
#> [1] TRUE
由reprex 包(v0.3.0)于 2019 年 8 月 1 日创建