【发布时间】:2021-04-25 22:00:34
【问题描述】:
我有以下函数n_bus_day_after,它在跳过银行假日和周六/周日的某个日期之后返回第 n 个日期。银行假期被定义为函数的一部分。它工作正常,但速度相当慢。你能给我一些想法如何加快这个功能吗?
n_bus_day_after <- function(.date, .n = 1){
.n <- .n - 1
following_date <- .date + days(1)
df <- data.frame(following_date) %>%
mutate(
following_date = case_when(
wday(following_date, week_start = 1) %in% c(6, 7) ~ NA_Date_, # weekend days
# czech bank holidays defined as the day of the month and month number
day(following_date) == 1 & month(following_date) == 1 |
day(following_date) == 1 & month(following_date) == 5 |
day(following_date) == 8 & month(following_date) == 5 |
day(following_date) == 5 & month(following_date) == 7 |
day(following_date) == 6 & month(following_date) == 7 |
day(following_date) == 28 & month(following_date) == 9 |
day(following_date) == 28 & month(following_date) == 10 |
day(following_date) == 17 & month(following_date) == 11 |
day(following_date) == 24 & month(following_date) == 12 |
day(following_date) == 25 & month(following_date) == 12 |
day(following_date) == 26 & month(following_date) == 12 |
# easter Friday and Monday defined using timeDate::Easter function
following_date == as.Date(Easter(year(following_date), shift = -2)) |
following_date == as.Date(Easter(year(following_date), shift = 1)) ~ NA_Date_,
T ~ following_date
)
)
if(is.na(df$following_date)){
Recall(following_date, .n + 1) # the following day is a bank holiday/Saturday/Sunday
}
else if(!is.na(df$following_date) & .n > 0){
Recall(following_date, .n = .n) # the following day is a work day, but need to add .n additional days
}
else if(!is.na(df$following_date) & .n == 0){
return(df$following_date) # the following day is a work day, and there are no additional days to add
}
else{
print("unexpected!!!!")
}
}
library(lubridate)
library(timeDate)
library(dplyr)
# an example function call
data.frame(a = today() + 0:1000) %>%
mutate(
b = as_date(map_dbl(a, ~n_bus_day_after(.x)))
)
【问题讨论】:
-
如果你想要速度,不要使用递归,也不要不必要地使用数据帧。在
count <- 0; while (count < .n) { date <- date + 1; if (is.bus.day(date)) count <- count + 1 }这样的循环中直接处理日期向量。 -
@user2554330 如果我避免递归和 data.frames,加速会有多重要?
-
您必须尝试并测量,但函数调用和数据帧索引在 R 中都是非常昂贵的操作。
-
我只是比较了两个函数,将
n加到x:一个递归加1,另一个通过循环加1n次来实现。当n = 10时,循环快了大约 8 倍。当n = 100时,它快了大约 25 倍。
标签: r performance date calendar