Constructing moving average over a categorical variable in R

前端 未结 2 1315
小鲜肉
小鲜肉 2021-01-03 10:55

I\'m looking to construct a moving average while aggregating a timeseries dataset over two categorical variables. While I\'ve seen a few other tutorials, none of them seem t

相关标签:
2条回答
  • 2021-01-03 11:22

    You could try zoo::rollmean

    df <- structure(list(Group = c("exceeded", "exceeded", "exceeded", 
    "exceeded", "exceeded", "exceeded", "exceeded", "exceeded", "exceeded", 
    "exceeded", "exceeded", "exceeded", "othergroup", "othergroup", 
    "othergroup", "othergroup", "othergroup", "othergroup", "othergroup", 
    "othergroup", "othergroup", "othergroup", "othergroup", "othergroup"
    ), Days = c(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
    0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L), DV = c(2859L, 
    2948L, 4412L, 5074L, 5098L, 5147L, 4459L, 4730L, 4643L, 4698L, 
    4818L, 4521L, 2859L, 2948L, 4412L, 5074L, 5098L, 5147L, 4459L, 
    4730L, 4643L, 4698L, 4818L, 4521L), X5DayMA = c(NA, NA, NA, NA, 
    4078L, 4536L, 4838L, 4902L, 4815L, 4735L, 4670L, 4682L, NA, NA, 
    NA, NA, 4078L, 4536L, 4838L, 4902L, 4815L, 4735L, 4670L, 4682L
    )), .Names = c("Group", "Days", "DV", "X5DayMA"), class = "data.frame", row.names = c(NA, 
    -24L))
    
    head(df)
         Group Days   DV X5DayMA
    1 exceeded    0 2859      NA
    2 exceeded    1 2948      NA
    3 exceeded    2 4412      NA
    4 exceeded    3 5074      NA
    5 exceeded    4 5098    4078
    6 exceeded    5 5147    4536
    
    library(plyr)
    library(zoo)
    ddply(
      df, "Group",
      transform,
      5daymean = rollmean(DV, 5, align="right", na.pad=TRUE ))
    
            Group Days   DV X5DayMA 5daymean
    1    exceeded    0 2859      NA       NA
    2    exceeded    1 2948      NA       NA
    3    exceeded    2 4412      NA       NA
    4    exceeded    3 5074      NA       NA
    5    exceeded    4 5098    4078   4078.2
    6    exceeded    5 5147    4536   4535.8
    7    exceeded    6 4459    4838   4838.0
    8    exceeded    7 4730    4902   4901.6
    9    exceeded    8 4643    4815   4815.4
    10   exceeded    9 4698    4735   4735.4
    11   exceeded   10 4818    4670   4669.6
    12   exceeded   11 4521    4682   4682.0
    13 othergroup    0 2859      NA       NA
    14 othergroup    1 2948      NA       NA
    15 othergroup    2 4412      NA       NA
    16 othergroup    3 5074      NA       NA
    17 othergroup    4 5098    4078   4078.2
    18 othergroup    5 5147    4536   4535.8
    19 othergroup    6 4459    4838   4838.0
    20 othergroup    7 4730    4902   4901.6
    21 othergroup    8 4643    4815   4815.4
    22 othergroup    9 4698    4735   4735.4
    23 othergroup   10 4818    4670   4669.6
    24 othergroup   11 4521    4682   4682.0
    

    or even faster with dplyr

    library(dplyr)
    df %.%
      dplyr:::group_by(Group) %.%
      dplyr:::mutate('5daymean' = rollmean(DV, 5, align="right", na.pad=TRUE ))
    

    OR the super fast data.table

    library(data.table)
    dft <- data.table(df)
    dft[ , `:=` ('5daymean' = rollmean(DV, 5, align="right", na.pad=TRUE )) , by=Group ]
    
    0 讨论(0)
  • 2021-01-03 11:32

    ave and filter:

    with(df, ave(DV, Group, FUN=function(x) filter(x,rep(1/5,5),sides=1)))
    # [1]     NA     NA     NA     NA 4078.2 4535.8 4838.0 4901.6 4815.4 4735.4
    #[11] 4669.6 4682.0     NA     NA     NA     NA 4078.2 4535.8 4838.0 4901.6
    #[21] 4815.4 4735.4 4669.6 4682.0
    
    0 讨论(0)
提交回复
热议问题