我想计算R中两个日期之间的工作日数,我使用以下代码:
Nweekdays <- Vectorize(function(a, b) + sum(!weekdays(seq(a, b, "days")) %in% c("Saturday", "Sunday")))
temp$diff <- Nweekdays(temp$from,temp$to)
此代码可以很好地处理小数据(.1百万),但代码在大数据(500万)上运行数小时,但仍然无法完成。
请建议更快地进行此计算的方法。
答案 0 :(得分:2)
以下是一些替代方案:
1)闯入整周和一周的一小部分如果它花费这么长时间的原因是由于长序列,那么这将确保序列永远不会超过一周。此处from
和to
是来自和来的日期:
weeks <- as.numeric(to - from) %/% 7
5*weeks + Nweekdays(7*weeks+from, to)
例如,使用这些from
和to
值,它会向Nweekdays
提供相同的结果:
from <- as.Date("2016-03-27")
to <- as.Date("2016-04-03")
weeks <- as.numeric(to - from) %/% 7
5*weeks + Nweekdays(7*weeks+from, to)
## [1] 5
Nweekdays(from, to)
## [1] 5
2)一周部分的预计算部分如果相距不到一周,那么我们可以预先计算7乘7矩阵m
的所有49种可能性是from和to的一周中的哪一天(第一行是Sun,下一行是Mon等,类似于列),然后定义Nweekdays2
,它计算整周数的5倍加上查找值部分周的m
。
# precompute m
sun <- as.Date("2012-01-01") # any Sunday will do
m <- outer(0:6, 0:6, function(x, y) Nweekdays(sun + x, sun + y + 7*(y < x)))
Nweekdays2 <- function(from, to) {
weeks <- as.integer(to - from) %/% 7L
5L * weeks + m[cbind(as.POSIXlt(from)$wday + 1L, as.POSIXlt(to)$wday + 1L)]
}
# test
set.seed(123)
from <- as.Date("2000-01-01") + 0:99
to <- from + sample(100, 100)
identical(Nweekdays2(from, to), Nweekdays(from, to))
## [1] TRUE
请注意,作为上述m
定义的替代方案,我们注意到通过检查m
它可以直接构造如下:
Rm <- row(diag(7)); Cm <- col(diag(7))
m <- (1 + 5 * (Cm < Rm)) * (Rm > 1) * (Cm < 7) - (Rm == 1 & Cm == 7) + Cm - Rm