2016-03-24 11 views
2

ich die Anzahl Wochentage zwischen zwei Daten in R berechnet werden soll und ich bin mit dem folgenden Code:Optimieren Berechnung der Anzahl der Wochentage

Nweekdays <- Vectorize(function(a, b) + sum(!weekdays(seq(a, b, "days")) %in% c("Saturday", "Sunday"))) 

temp$diff <- Nweekdays(temp$from,temp$to) 

Dieser Code funktioniert absolut in Ordnung mit einer kleinen Daten (0,1 Mio.) aber der Code läuft stundenlang auf großen Daten (5 Millionen) und wird immer noch nicht abgeschlossen.

Bitte schlagen Sie vor, diese Berechnung schneller durchzuführen.

+0

Aus Interesse, was sind die Bereiche von 'aus 'und' to' (dh min und max)? – rbm

Antwort

2

Hier sind einige Alternativen:

1) brechen in ganzen Wochen und Bruchteil einer Woche Wenn der Grund, dass es so lange dauert wegen der langen Sequenzen ist dann dies gewährleisten wird, dass die Folge nie mehr ist als eine Woche. Hier from und to sind die von und zu Terminen:

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

Zum Beispiel mit diesen from und to Werte es identische Ergebnisse zu Nweekdays gibt:

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) Precompute Bruchteil einer Woche Teil Wenn von und nach weniger als eine Woche auseinander liegen, können wir alle 49 Möglichkeiten in einer 7 mal 7 Matrix m vorberechnen, deren Zeilen und Spalten den Wochentag von und nach darstellen (die erste Zeile ist Sonne, nächste ist Mon usw. und ähnlich für Spalten) und definieren Sie dann Nweekdays2, die die fünffache Anzahl der ganzen Wochen plus den Nachschlagewert in m für die Teilwoche berechnet.

# 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 

Beachten Sie, dass als Alternative zur Definition von m oben wir feststellen, dass m durch Einsicht, dass es direkt wie folgt aufgebaut sein könnte:

Rm <- row(diag(7)); Cm <- col(diag(7)) 
m <- (1 + 5 * (Cm < Rm)) * (Rm > 1) * (Cm < 7) - (Rm == 1 & Cm == 7) + Cm - Rm 
+0

Zugegebene Lösung (2). –

+0

zu und von sind mehr als eine Woche auseinander, fast 200 Tage Unterschied gibt es auch in einigen Fällen, kann ich das noch nutzen? – user6108954

+0

Ja, natürlich. Der ganze Sinn von (1) besteht darin, es in die Summe zweier Größen zu zerlegen, von denen eine eine Woche oder mehr auseinander ist und eine davon weniger ist. Die erste ist nur 5 mal die Anzahl der Wochen und die zweite wird mit Nweekdays aus der Frage berechnet. (2) funktioniert genauso, außer dass die Schlüsselberechnung in dem Abschnitt vorberechnet wird, der weniger als eine Woche auseinander liegt. –

Verwandte Themen