3 votes

calculer des statistiques basées sur une fenêtre dynamique en utilisant dplyr

J'essaie d'utiliser dplyr dans R pour calculer des statistiques glissantes (moyenne, sd, etc) à partir d'une fenêtre dynamique basée sur des dates et pour des modèles spécifiques. Par exemple, au sein de groupes d'éléments, je voudrais calculer la moyenne mobile pour toutes les données 10 jours auparavant. Les dates des données ne sont pas séquentielles et ne sont pas complètes, je ne peux donc pas utiliser une fenêtre fixe.

Une façon de le faire est d'utiliser rollapply en faisant référence à la largeur de la fenêtre comme indiqué ci-dessous. Cependant, j'ai du mal à calculer la largeur dynamique. Je préférerais une méthode qui omette l'étape intermédiaire de calcul de la fenêtre et qui calcule simplement sur la base de la date_lookback. Voici un petit exemple.

J'ai utilisé des boucles for pour faire cela, mais elles sont très lentes.

    library(dplyr)
library(zoo)

date_lookback <- 10 #days to look back for rolling calcs

df <- data.frame(label = c(rep("a",5),rep("b",5)),
                 date = as.Date(c("2017-01-02","2017-01-20",
                                  "2017-01-21","2017-01-30","2017-01-31","2017-01-05",
                                  "2017-01-08","2017-01-09","2017-01-10","2017-01-11")),
                data = c(790,493,718,483,825,186,599,408,108,666),stringsAsFactors = FALSE) %>%
  mutate(.,
         cut_date = date - date_lookback, #calcs based on sample since this date
         dyn_win = c(1,1,2,3,3,1,2,3,4,5), ##!! need to calculate this vector??
         roll_mean = rollapply(data, align = "right", width = dyn_win, mean),
         roll_sd = rollapply(data, align = "right", width = dyn_win, sd))

Ce sont les résultats roll_mean et roll_sd que je recherche :

> df
   label       date data   cut_date dyn_win roll_mean  roll_sd
1      a 2017-01-02  790 2016-12-23       1  790.0000       NA
2      a 2017-01-20  493 2017-01-10       1  493.0000       NA
3      a 2017-01-21  718 2017-01-11       2  605.5000 159.0990
4      a 2017-01-30  483 2017-01-20       3  564.6667 132.8847
5      a 2017-01-31  825 2017-01-21       3  675.3333 174.9467
6      b 2017-01-05  186 2016-12-26       1  186.0000       NA
7      b 2017-01-08  599 2016-12-29       2  392.5000 292.0351
8      b 2017-01-09  408 2016-12-30       3  397.6667 206.6938
9      b 2017-01-10  108 2016-12-31       4  325.2500 222.3921
10     b 2017-01-11  666 2017-01-01       5  393.4000 245.5928

Merci d'avance.

0voto

Pdubbs Points 1597

Vous pouvez essayer de référencer explicitement votre jeu de données dans l'appel dplyr :

date_lookback <- 10 #days to look back for rolling calcs

df <- data.frame(label = c(rep("a",5),rep("b",5)),
                 date = as.Date(c("2017-01-02","2017-01-20",
                                  "2017-01-21","2017-01-30","2017-01-31","2017-01-05",
                                  "2017-01-08","2017-01-09","2017-01-10","2017-01-11")),
                 data = c(790,493,718,483,825,186,599,408,108,666),stringsAsFactors = FALSE)

df %>%
  group_by(date,label) %>%
  mutate(.,
         roll_mean = mean(ifelse(df$date >= date-date_lookback & df$date <= date & df$label == label,
                                 df$data,NA),na.rm=TRUE),
         roll_sd = sd(ifelse(df$date >= date-date_lookback & df$date <= date & df$label == label,
                             df$data,NA),na.rm=TRUE))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X