【问题标题】:Calculate rolling mean with a minimum number of non-na values in the moving window计算移动窗口中非 na 值最少的滚动平均值
【发布时间】:2022-01-09 21:24:18
【问题描述】:

从这个例子可以看出,计算运行平均值很容易:

data <- data.frame(dats=c(3,4,NA,4,NA,NA,6,NA,8,1,4,NA,2,NA,NA,6,NA,NA,9,5,NA,8,NA,3))
data <- data %>% mutate(rmean = caTools::runmean(dats, 3, endrule="constant"))

但在某些情况下,平均值仅根据数据中唯一的 no-na 值计算得出。如何防止这种情况并指定仅当运行窗口中的一定数量的非 na 值用于均值计算时才获得 runmean?

【问题讨论】:

    标签: r mean


    【解决方案1】:

    如果没有至少 2 个非 NA 使用 rollapply,则 rmean 使用 NA,rmean2 使用两次 runmean 调用来实现,而 rmean3 是问题中计算的值。

    library(zoo)
    
    mean2 <- function(x) if (sum(!is.na(x)) >= 2) mean(x, na.rm = TRUE) else NA
    data %>% 
     mutate(
       rmean = rollapply(dats, 3, mean2, partial = TRUE) |> na.fill(c("extend", NA)),
       rmean2 = ifelse(runmean(!is.na(dats), 3, endrule = "constant") > 2/3 - 1e-5, 
                     runmean(dats, 3, endrule = "constant"), NA),
       rmean3 = runmean(dats, 3, endrule = "constant"))
    

    给予:

       dats    rmean   rmean2   rmean3
    1     3 3.500000 3.500000 3.500000
    2     4 3.500000 3.500000 3.500000
    3    NA 4.000000 4.000000 4.000000
    4     4       NA       NA 4.000000
    5    NA       NA       NA 4.000000
    6    NA       NA       NA 6.000000
    7     6       NA       NA 6.000000
    8    NA 7.000000 7.000000 7.000000
    9     8 4.500000 4.500000 4.500000
    10    1 4.333333 4.333333 4.333333
    11    4 2.500000 2.500000 2.500000
    12   NA 3.000000 3.000000 3.000000
    13    2       NA       NA 2.000000
    14   NA       NA       NA 2.000000
    15   NA       NA       NA 6.000000
    16    6       NA       NA 6.000000
    17   NA       NA       NA 6.000000
    18   NA       NA       NA 9.000000
    19    9 7.000000 7.000000 7.000000
    20    5 7.000000 7.000000 7.000000
    21   NA 6.500000 6.500000 6.500000
    22    8       NA       NA 8.000000
    23   NA 5.500000 5.500000 5.500000
    24    3 5.500000 5.500000 5.500000
    

    【讨论】:

      【解决方案2】:

      如果您不介意使用 zoo 库,那么一种解决方案是定义自定义函数:

      rolling_mean = function(x) {                                                                 
              ifelse(length(na.omit(x)) > 2, mean(x), "too_many_missing")
      }
      

      然后使用rollapply翻转数据集:

      library(zoo)
      library(dplyr)
      data %>% 
          mutate(remean = rollapply(dats, width=3, FUN=rolling_mean,  partial = 2)) %>%
          na.fill(c("extend", NA))
      

      当然,您可以更改自定义函数中的值来改变非NA值的数量。

      此外,您可能希望将 "too_many_missing" 字符串更改为 NA 以避免将整列强制转换为字符变量。

         dats           remean
      1     3             <NA>
      2     4 too_many_missing
      3    NA too_many_missing
      4     4 too_many_missing
      5    NA too_many_missing
      6    NA too_many_missing
      7     6 too_many_missing
      8    NA too_many_missing
      9     8 too_many_missing
      10    1 4.33333333333333
      11    4 too_many_missing
      12   NA too_many_missing
      13    2 too_many_missing
      14   NA too_many_missing
      15   NA too_many_missing
      16    6 too_many_missing
      17   NA too_many_missing
      18   NA too_many_missing
      19    9 too_many_missing
      20    5 too_many_missing
      21   NA too_many_missing
      22    8 too_many_missing
      23   NA too_many_missing
      24    3             <NA>
      
      

      【讨论】:

      • 建议使用 NA 而不是字符串,以便结果保持数字。还可以使用 na.fill(rollapply(...), c("extend", NA)) 将第一个和最后一个非 NA 扩展到末尾。
      猜你喜欢
      • 1970-01-01
      • 2021-07-03
      • 2020-07-12
      • 1970-01-01
      • 2018-05-23
      • 1970-01-01
      • 2018-05-08
      • 2021-11-04
      • 2016-05-26
      相关资源
      最近更新 更多