优化工作日数量的计算

时间:2016-03-24 10:47:45

标签: r

我想计算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万)上运行数小时,但仍然无法完成。

请建议更快地进行此计算的方法。

1 个答案:

答案 0 :(得分:2)

以下是一些替代方案:

1)闯入整周和一周的一小部分如果它花费这么长时间的原因是由于长序列,那么这将确保序列永远不会超过一周。此处fromto是来自和来的日期:

weeks <- as.numeric(to - from) %/% 7
5*weeks + Nweekdays(7*weeks+from, to)

例如,使用这些fromto值,它会向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