从以下开始:
dates <- yday(ceiling_date(dmy(sapply(1:11, function(x) paste0("01/", x, "/2009"))), "month") %m-% days(1))
foo <- data.frame(id = 1:1000000) %>%
mutate(
datdeb = round(runif(n(), 1, 365)),
datfin = round(runif(n(), datdeb, 365)),
etp = runif(n()),
group = round(runif(n(), 1, 1000))
)
我想要做的最基本的事情是:
for(i in 1:11){
foo <- foo %>%
group_by(group) %>%
mutate(
test = sum((dates[i] >= datdeb & dates[i] <= datfin))
) %>%
rename(!!paste0("size_date", dates[i]) := "test")
}
res1 <- foo %>%
mutate(
m_size = rowMeans(across(starts_with("size_date")))
) %>%
group_by(group) %>%
summarise(
m_size = mean(m_size)
)
现在,我希望以最快的方式完成此操作,因为我要应用它的数据集非常庞大。
对于第一部分,我想到了以下替代方案:
foo <- bind_cols(foo, map_dfc(1:11, ~ foo %>%
group_by(group) %>%
transmute(!!paste0("size_date", dates[.x]) := sum((dates[.x] >= datdeb & dates[.x] <= datfin)))
) %>% select(starts_with("size_date")))
但是令我有些惊讶的是,当使用tictoc进行基准测试时,这种方法结果比较慢。
针对第二部分,我提出了另外两个选项:
res2 <- foo %>%
mutate(
m_size = rowMeans(across(starts_with("size_date")))
) %>%
group_by(group) %>%
summarise(
m_size = m_size[1]
)
res3 <- foo %>%
group_by(group) %>%
slice(1) %>%
mutate(
m_size = rowMeans(across(starts_with("size_date")))
)
毫不意外,最后一种选择速度要快得多。
我在想是否有更快(和更优雅?)的方法来完成这个任务?特别是,是否可以以增量累积均值的方式智能地将两个步骤结合起来?谢谢!
tidyverse
中吗?因为更快的前进很可能意味着抛弃它。 - user10917479dtplyr
。最好的两个世界...dplyr
API 和data.table
速度的结合。 - user10917479