dplyr 中的变异函数不适用于滚动均值/移动平均线

Mutate function in dplyr not working with Rolling Means/ Moving Averages

首先,无论您是否有意见,感谢您花时间查看我的问题。

让我分解一下我在做什么,示例数据集和错误。

我目前拥有的是几个不同 ID 的数据,这些 ID 列出了每天的分散情况。 (您将在下面看到)。我想遍历日期并向数据添加两列:滚动均值列和滚动标准差列

到目前为止我写出的代码是这样的:

library(zoo)
Testing1 <- function(dataset, k) {
ops <- data.frame()  
for (i in unique(dataset$Date)) {  
ops <- dataset %>% mutate(rolling_mean = rollmean(dataset$Dispersion,k)) %>% 
mutate(rolling_std = rollapply(dataset$Dispersion, width = k, FUN = sd))
}
Results <<- ops 
}

但是,我收到以下错误:

Error in mutate_impl(.data, dots) : Column rolling_mean must be length 30 (the number of rows) or one, not 26

我假设行差异是由于我为滚动平均值指定了 5 天 window,这意味着它不会计算前 4 行。但是我该如何告诉 R 在这些行上输入 NA 是可以的呢?或者如果你们有任何其他解决方案,那也可以。请帮忙。

这是数据样本:

Identifier  Date    Dispersion
1000    2/15/2018   0.390
1000    2/16/2018   0.664
1000    2/17/2018   0.526
1000    2/18/2018   0.933
1000    2/19/2018   0.009
1000    2/20/2018   0.987
1000    2/21/2018   0.517
1000    2/22/2018   0.641
1000    2/23/2018   0.777
1000    2/24/2018   0.613
1001    2/15/2018   0.617
1001    2/16/2018   0.234
1001    2/17/2018   0.303
1001    2/18/2018   0.796
1001    2/19/2018   0.359
1001    2/20/2018   0.840
1001    2/21/2018   0.291
1001    2/22/2018   0.699
1001    2/23/2018   0.882
1001    2/24/2018   0.467
1002    2/15/2018   0.042
1002    2/16/2018   0.906
1002    2/17/2018   0.077
1002    2/18/2018   0.156
1002    2/19/2018   0.350
1002    2/20/2018   0.060
1002    2/21/2018   0.457
1002    2/22/2018   0.770
1002    2/23/2018   0.433
1002    2/24/2018   0.366

我会看看 tibbletime

假设您的数据框名为 mydata 并且 Date 列是一个字符:首先转换 Date,然后转换为 time-aware tibble:

library(dplyr)
library(tibbletime)

mydata <- mydata %>% 
  mutate(Date = as.Date(Date, "%m/%d/%Y")) %>% 
  as_tbl_time(index = Date)

现在您可以为滚动均值和 sd 定义函数:

mean_5 <- rollify(mean, window = 5) 
sd_5   <- rollify(sd,   window = 5) 

mydata %>% 
  mutate(rolling_mean = mean_5(Dispersion),
         rolling_std  = sd_5(Dispersion))

# A time tibble: 30 x 5
# Index: Date
   Identifier Date       Dispersion rolling_mean rolling_std
        <int> <date>          <dbl>        <dbl>       <dbl>
 1       1000 2018-02-15      0.39        NA          NA    
 2       1000 2018-02-16      0.664       NA          NA    
 3       1000 2018-02-17      0.526       NA          NA    
 4       1000 2018-02-18      0.933       NA          NA    
 5       1000 2018-02-19      0.009        0.504       0.342
 6       1000 2018-02-20      0.987        0.624       0.393
 7       1000 2018-02-21      0.517        0.594       0.394
 8       1000 2018-02-22      0.641        0.617       0.393
 9       1000 2018-02-23      0.777        0.586       0.367
10       1000 2018-02-24      0.613        0.707       0.182
# ... with 20 more rows

你得到这个错误是因为滚动的长度 means/stds 与 Dispersion 的长度不匹配。只需在 means/stds 向量的开头添加 k - 1 NAs。

下面是一个工作示例。您可以根据自己的需要进行修改。

my_function <- function(df, k) {
  df %>%
    mutate(
      rolling_mean = c(rep(NA, k - 1), rollmean(Dispersion, k)),
      rolling_std = c(rep(NA, k - 1), rollapply(Dispersion, width = k, FUN = sd))
    )
}

例如,您可能想要添加 group_by 来为每个 Identifier:

计算这些值
my_function <- function(df, k) {
  df %>%
    group_by(Identifier) %>%
    mutate(
      rolling_mean = c(rep(NA, k - 1), rollmean(Dispersion, k)),
      rolling_std = c(rep(NA, k - 1), rollapply(Dispersion, width = k, FUN = sd))
    )
}

更新跟进@G。格洛腾迪克的评论:

事实证明包 zoo 已经具有用于 NA 处理的全面功能,将上面给出的代码重构为:

my_function <- function(df, k) {
  df %>%
    mutate(
      rolling_mean = rollmeanr(Dispersion, k, fill = NA),
      rolling_std = rollapplyr(Dispersion, width = k, FUN = sd, fill = NA)
    )
}