【问题标题】:Generating mean column calculated over a time window defined by a categorical variable in R生成在由 R 中的分类变量定义的时间窗口上计算的平均列
【发布时间】:2020-03-30 11:30:53
【问题描述】:

我有一个如下所示的数据框:

structure(list(week  = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 
               freq  = c(0, 4.34, 1.24, 0, 5.26, 0, 7.12, 3.70, 0, 0), 
               event = c(0, 0, 0, 0, 0, 0, 1, 0, 0, 0)), 
          row.names = c(NA, -10L), 
          class = c("tbl_df", "tbl", "data.frame"))

我需要做的是创建一个新列,对应于 event=1,计算前几周 -2 到 -4 之间窗口的频率平均值,由变量 week 标识。 例如,由于第 7 周的 event=1,我想平均第 2、3、4 和 5 周的频率。每次 event 等于 1 时都必须重复此操作。该平均值应在新列中报告在 event=1 的行中。

同样,我需要生成另一列,其平均值为 window -1 ; +2 相对于 event=1,所以在这种情况下是第 6 周到第 9 周。

最终的结果应该是这样的:

week    freq    event     mean1     mean2
1       0       0         NA        NA
2       4.34    0         NA        NA
...
7       7.12    1         2.71      2.705
...

如果您能帮我解决这个问题,我将不胜感激,我已经阅读了几个类似的主题,但我找不到解决这个特定问题的方法。

【问题讨论】:

    标签: r dataframe moving-average


    【解决方案1】:

    您的问题有几个问题。你的dput 不工作,所以我已经修好了。其次,你说你想在 -4 到 -2 周的时间范围内工作。那是第 3 周、第 4 周和第 5 周,而不是第 2、3、4 和 5 周。在本例中,我假设您的意思是 -5 到 -2 周,尽管您将看到这很容易更改。

    以下函数将允许您在frequency 列中指定相对于窗口的开始和停止位置。

    使用诸如data.table 之类的库可以使这个函数更加简洁和高效,但是我在这里给出了一个基本的 R 解决方案,并尝试以使逻辑易于遵循的方式编写它:

    relative_window <- function(variable, start, stop)
    {
      result <- rep(NA, length(variable))
      if(start > stop | start > length(variable) | stop > length(variable)) return(result)
      start_indices <- seq_along(variable) + start
      stop_indices  <- seq_along(variable) + stop
      ss <- which(start_indices > 0 & stop_indices <= length(variable))
      start_indices <- start_indices[ss]
      stop_indices <- stop_indices[ss]
      index <- seq_along(variable)[ss]
      for(i in seq_along(ss))
      {
        result[index[i]] <- mean(variable[start_indices[i]:stop_indices[i]])
      }
      return(result)
    }
    

    所以现在你可以这样做了:

    df$mean1 <- ifelse(df$event == 1, relative_window(df$freq, -5, -2), NA)
    df$mean2 <- ifelse(df$event == 1, relative_window(df$freq, -1, 2), NA)
    

    这给了你

    df
    #>    week freq event mean1 mean2
    #> 1     1 0.00     0    NA    NA
    #> 2     2 4.34     0    NA    NA
    #> 3     3 1.24     0    NA    NA
    #> 4     4 0.00     0    NA    NA
    #> 5     5 5.26     0    NA    NA
    #> 6     6 0.00     0    NA    NA
    #> 7     7 7.12     1  2.71 2.705
    #> 8     8 3.70     0    NA    NA
    #> 9     9 0.00     0    NA    NA
    #> 10   10 0.00     0    NA    NA
    

    reprex package (v0.3.0) 于 2020 年 3 月 30 日创建

    【讨论】:

      【解决方案2】:

      这是一个data.table 解决方案,假设我理解正确:

      library(data.table)
      setDT(car_weekly)
      car_weekly[, mean1 := fifelse(event == 1, shift(frollmean(freq, n = 4), 2), NA_real_) ]
      car_weekly[, mean2 := fifelse(event == 1, shift(frollmean(freq, n = 4), -2), NA_real_)]
      
      
         week freq event mean1 mean2
       1:    1 0.00     0    NA    NA
       2:    2 4.34     0    NA    NA
       3:    3 1.24     0    NA    NA
       4:    4 0.00     0    NA    NA
       5:    5 5.26     0    NA    NA
       6:    6 0.00     0    NA    NA
       7:    7 7.12     1  2.71 2.705
       8:    8 3.70     0    NA    NA
       9:    9 0.00     0    NA    NA
      10:   10 0.00     0    NA    NA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-08
        • 2014-08-30
        相关资源
        最近更新 更多