我正在try 通过ID列表对同一数据帧进行子集.我有一个大约50,000行的数据帧和大约1,000个数据帧的列表.列表中的每个数据框具有100到1000行,并且具有相同的 struct .
请考虑以下示例:
df1 <- data.frame(id = sample(sample(1000:3000, 1000), 50000, TRUE), info = runif(50000, 200, 300))
set.seed(1)
l <- replicate(1000,
data.frame(id = sample(1000:3000, sample(400:700, 1), replace = TRUE)),
simplify = FALSE)
我想根据l
中的ID来子集df1
.我可以通过执行半连接或使用%in%
设置子集来完成此操作:
library(dplyr)
semi_join(df1, l[[1]], "id")
df1[df1$id %in% l[[1]]$id, ]
我正在寻找一种快速的解决方案,可以扩展到数千个数据帧的列表.到目前为止,我只用了lapply
个(但可能会有更快的、矢量化的解决方案).
lapply(l, \(x) semi_join(df1, x, "id"))
以下是解决方案的起始基准:
bc <-
bench::mark(dplyr = lapply(l, \(x) semi_join(df1, x, "id")),
baseR = lapply(l, \(x) df1[df1$id %in% x$id, ]),
unique = lapply(l, \(x) df1[df1$id %in% unique(x$id), ]),
data.table = {df2 <- setDT(df1); lapply(l, \(x) df2[df2$id %in% unique(x$id), ])},
iterations = 10, check = FALSE)
#> bc
# A tibble: 4 × 13
# expression min median `itr/sec` mem_alloc gc/se…¹ n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
#1 dplyr 2.25s 2.43s 0.416 1.64GB 4.03 10 97
#2 baseR 9.04s 9.55s 0.105 1.56GB 0.536 10 51
#3 unique 10.3s 10.95s 0.0912 1.57GB 0.420 10 46
#4 data.table 10.21s 10.9s 0.0916 979.5MB 0.458 10 50
任何程序包都可以使用.