gpt4 book ai didi

r - dplyr bind_rows 执行时间指数

转载 作者:行者123 更新时间:2023-12-01 03:18:36 42 4
gpt4 key购买 nike

我有一个要合并的小标题列表(长度 = 5000)。他们都有相同的列,所以我想到了使用 dplyr::bind_rows 合并。从表面上看,每个添加的 tibble 绑定(bind)行非常快,但是随着添加更多 tibble,执行时间呈指数增长而不是线性增加。
进行了一些谷歌搜索后,它与此处观察到的错误非常相似:https://github.com/tidyverse/dplyr/issues/1396。尽管该错误应该已在 bind_rows 内部修复,但我仍然看到每个 tibble 所用时间呈指数增长。

library(foreach)
library(tidyverse)
set.seed(123456)
tibbles <- foreach(i = 1:200) %do% {
tibble(a = rnorm(10000),
b = rep(letters[1:25], 400),
c = rnorm(10000))
}
times <- foreach(i = 1:200) %do% {
system.time(tibbles[1:i] %>%
purrr::reduce(bind_rows))
}

times %>%
map_dbl(.f = ~.x[3]) %>%
plot(ylab = "time [s] per added tibble")
任何想法为什么会这样以及如何解决它?
谢谢。
elapsed_time

最佳答案

我的猜测是每次你调用rbind , R 必须分配一组新的列并将数据复制过来。这将导致时间的二次增长。

尝试预先分配列:

system.time({
n <- vapply(tibbles, nrow, 0)
ntot <- sum(n)
cols <- list(a = numeric(ntot), b = character(ntot), c = numeric(ntot))

off <- 0
for (i in seq_along(tibbles)) {
ix <- off + seq_len(n[[i]])
for (j in seq_along(cols)) {
cols[[j]][ix] <- tibbles[[i]][[j]]
}
off <- off + n[[i]]
}

result <- as_tibble(cols)
})
#> user system elapsed
#> 0.073 0.012 0.085

purrr::reduce 比较方法:
system.time(tibbles[1:200] %>% purrr::reduce(bind_rows))
#> user system elapsed
#> 4.888 2.013 6.928

虽然,正如 aosmith 指出的那样,在您的情况下,最好只使用 bind_rows :
system.time(result <- bind_rows(tibbles))
#> user system elapsed
#> 0.039 0.005 0.044

关于r - dplyr bind_rows 执行时间指数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47556093/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com