R: Rolling Window-Funktion mit einstellbarem Fenster und Stufengröße für unregelmäßig beabstandete Beobachtungen

Angenommen, es gibt einen 2-Spalten-Datenrahmen mit einer Zeit- oder Entfernungsspalte, die sequentiell zunimmt, und einer Beobachtungsspalte, die hier und da NAs haben kann. Wie kann ich eine Schiebefensterfunktion effizient verwenden, um eine Statistik, beispielsweise einen Mittelwert, für die Beobachtungen in einem Fenster mit der Dauer X (z. B. 5 Sekunden) zu erhalten? Schieben Sie das Fenster über Y Sekunden (z. B. 2,5 Sekunden), wiederholen Sie ...Die Anzahl der Beobachtungen im Fenster basiert auf der Zeitspalte, daher können sowohl die Anzahl der Beobachtungen pro Fenster als auch die Anzahl der Beobachtungen zum Verschieben des Fensters variieren Die Funktion sollte jede Fenstergröße bis zur Anzahl der Beobachtungen und einer Schrittgröße akzeptieren.

Hier sind Beispieldaten (siehe "Bearbeiten:"für ein größeres Sample Set)

set.seed(42)
dat <- data.frame(time = seq(1:20)+runif(20,0,1))
dat <- data.frame(dat, measure=c(diff(dat$time),NA_real_))
dat$measure[sample(1:19,2)] <- NA_real_
head(dat)
      time   measure
1 1.914806 1.0222694
2 2.937075 0.3490641
3 3.286140        NA
4 4.830448 0.8112979
5 5.641746 0.8773504
6 6.519096 1.2174924

Gewünschte Ausgabe für den speziellen Fall eines 5-Sekunden-Fensters, 2,5-Sekunden-Schritt, erstes Fenster von -2,5 bis 2,5, na.rm = FALSE:

 [1] 1.0222694
 [2]        NA
 [3]        NA
 [4] 1.0126639
 [5] 0.9965048
 [6] 0.9514456
 [7] 1.0518228
 [8]        NA
 [9]        NA
[10]        NA

Erklärung: In der gewünschten Ausgabe sucht das allererste Fenster nach Zeiten zwischen -2,5 und 2,5. Eine Messbeobachtung befindet sich in diesem Fenster, und es ist keine NA, daher erhalten wir diese Beobachtung: 1.0222694. Das nächste Fenster ist von 0 bis 5 und es gibt eine NA im Fenster, also bekommen wir NA. Gleiches gilt für das Fenster von 2,5 bis 7,5. Das nächste Fenster ist von 5 bis 10. Es gibt 5 Beobachtungen im Fenster, keine sind NA. Wir erhalten also den Durchschnitt dieser 5 Beobachtungen (d. H. Mittelwert (dat [dat $ time> 5 & dat $ time <10, 'measure'])

Was ich versucht habe: Folgendes habe ich für den speziellen Fall eines Fensters versucht, bei dem die Schrittgröße 1/2 der Fensterdauer beträgt:

windo <- 5  # duration in seconds of window

# partition into groups depending on which window(s) an observation falls in
# When step size >= window/2 and < window, need two grouping vectors
leaf1 <- round(ceiling(dat$time/(windo/2))+0.5)
leaf2 <- round(ceiling(dat$time/(windo/2))-0.5) 

l1 <- tapply(dat$measure, leaf1, mean)
l2 <- tapply(dat$measure, leaf2, mean)

as.vector(rbind(l2,l1))

Nicht flexibel, nicht elegant, nicht effizient. Wenn die Schrittgröße nicht 1/2 Fenstergröße ist, funktioniert der Ansatz nicht wie er ist.

Irgendwelche Gedanken zu einer allgemeinen Lösung für diese Art von Problem? Jede Lösung ist akzeptabel. Je schneller, desto besser. Ich bevorzuge jedoch Lösungen mit Basis-R, data.table, Rcpp und / oder paralleler Berechnung. In meinem realen Datensatz sind mehrere Millionen Beobachtungen in einer Liste von Datenrahmen enthalten (der maximale Datenrahmen beträgt ~ 400.000 Beobachtungen).

Unten finden Sie eine zusätzliche Information: Ein größeres Beispielset

Bearbeiten: Auf Anfrage finden Sie hier einen größeren, realistischeren Beispieldatensatz mit viel mehr NAs und der minimalen Zeitspanne (~ 0,03). Um es klar zu machen, enthält die Liste der Datenrahmen kleine wie die oben genannten sowie folgende und größere:

set.seed(42)
dat <- data.frame(time = seq(1:50000)+runif(50000, 0.025, 1))
dat <- data.frame(dat, measure=c(diff(dat$time),NA_real_))
dat$measure[sample(1:50000,1000)] <- NA_real_
dat$measure[c(350:450,3000:3300, 20000:28100)] <- NA_real_
dat <- dat[-c(1000:2000, 30000:35000),] 

# a list with a realistic number of observations:
dat <- lapply(1:300,function(x) dat)

Antworten auf die Frage(5)

Ihre Antwort auf die Frage