2017-02-10 5 views
0

Ich versuche in den letzten 6 Monaten einen rollenden Mittelwert für einen Datensatz zu erstellen. Die Daten sind täglich und haben mehr als 100.000 Zeilen, von denen ich unten ein Beispiel zur Verfügung gestellt habe.Rollender Mittelwert mit unterschiedlicher Anzahl von Beobachtungen

# A tibble: 100 × 5 
     ID MONTH  DATE VALUE R_MEAN 
    <fctr> <dbl>  <date> <dbl> <dbl> 
1  634 20160200 2016-02-03  2 0.000000 
2 1700 20150300 2015-03-02  3 0.000000 
3 1700 20150400 2015-04-01  7 3.000000 
4 1700 20150400 2015-04-09  1 5.000000 
5 1700 20150700 2015-07-02 26 3.666667 
6 1700 20150800 2015-08-03  1 9.250000 
7 1700 20150900 2015-09-01  2 7.600000 
8 1700 20151000 2015-10-01  5 7.400000 
9 1700 20151000 2015-10-07 10 7.833333 
10 1700 20151100 2015-11-02  8 8.800000 
# ... with 90 more rows 

Mein Ziel ist es, einen gleitenden Durchschnitt in den letzten 6 Monaten zu schaffen, so zum Beispiel für eine ID: X und DATE-Wert von 20.160.101 ich den Mittelwert aller Zeilen erhalten möchten, die die gleiche ID haben und wobei der DATE-Wert zwischen 20150601 und 20160101 liegt. Wenn keine vorherigen Werte verfügbar sind, nehme ich einen Durchschnittswert von Null an.

Ich dachte an eine Art erweiterter Rasteransatz, aber da ich viele IDs (fast 30.000) habe, würde eine tägliche Erweiterung des Rasters über einen Zeitraum von 2 Jahren zu einem enormen Raster führen.

Antwort

2

Here I dplyr verwenden. I inner_join die Tabelle für sich selbst, dann die relevanten vorherigen Zeilen pro Zeile in den Quelldaten filtern und den Mittelwert berechnen.

Schließlich I left_join die ursprünglichen Daten über die verarbeiteten Daten und ersetzen NA mit coalesce.

Das 6-Monats-Fenster wird berechnet, indem 182 Tage vom DATE abgezogen werden. Sie können auch lubridate verwenden, um einen Zeitraum in Monaten zu erstellen. Persönlich bevorzuge ich die Arbeit mit einem festen Fenster von Tagen, das nicht von der unterschiedlichen Anzahl der Tage abhängt, die jeder Monat hat.

str <- ' 
row ID MONTH DATE VALUE R_MEAN 
1 634 20160200 2016-02-03  2 0.000000 
2 1700 20150300 2015-03-02  3 0.000000 
3 1700 20150400 2015-04-01  7 3.000000 
4 1700 20150400 2015-04-09  1 5.000000 
5 1700 20150700 2015-07-02 26 3.666667 
6 1700 20150800 2015-08-03  1 9.250000 
7 1700 20150900 2015-09-01  2 7.600000 
8 1700 20151000 2015-10-01  5 7.400000 
9 1700 20151000 2015-10-07 10 7.833333 
10 1700 20151100 2015-11-02  8 8.800000 
' 

file <- textConnection(str) 

raw <- read.table(file, header = T) 

library(dplyr) 

df <- raw %>% mutate(DATE = as.Date(DATE,'%Y-%m-%d')) 

prev <- df %>% inner_join(df, by = 'ID') %>% 
    filter(DATE.y > DATE.x-182, DATE.y < DATE.x) %>% 
    group_by(row.x) %>% summarise(meanVALUE = mean(VALUE.y)) %>% 
    rename(row = row.x) 

df %>% left_join(prev, by='row') %>% mutate(meanVALUE = coalesce(meanVALUE,0)) 

Ergebnis:

row ID MONTH  DATE VALUE R_MEAN meanVALUE 
1 1 634 20160200 2016-02-03  2 0.000000 0.000000 
2 2 1700 20150300 2015-03-02  3 0.000000 0.000000 
3 3 1700 20150400 2015-04-01  7 3.000000 3.000000 
4 4 1700 20150400 2015-04-09  1 5.000000 5.000000 
5 5 1700 20150700 2015-07-02 26 3.666667 3.666667 
6 6 1700 20150800 2015-08-03  1 9.250000 9.250000 
7 7 1700 20150900 2015-09-01  2 7.600000 8.750000 
8 8 1700 20151000 2015-10-01  5 7.400000 7.500000 
9 9 1700 20151000 2015-10-07 10 7.833333 7.000000 
10 10 1700 20151100 2015-11-02  8 8.800000 8.800000 
+0

Großartig! Das hat wunderbar funktioniert! – Michael

0

Vielleicht hilft:

for (i in 1:levels(df$ID)) 
    mean(df$value[df$DATE>(Sys.date()-182) & 
        df$ID==levels(df$ID)[i]], 
      na.rm=T) 
+0

Ich mag würde ein Roll in den letzten 6 Monaten für den Wert von DATE in jeder Zeile bedeuten haben. Daher möchte ich nicht auf die vergangenen 6 Monate basierend auf heute schauen. Vielen Dank für Ihre Antwort noch. – Michael

Verwandte Themen