创建一列中每第三行的滚动平均值,将其存储在一个新变量中

问题描述

我正在尝试获取特定列中每第三(或第二)行的滚动平均值。更准确地说,我希望将滚动平均值存储在现有数据框中的新变量中。

我尝试使用此功能

w %>% 
  mutate(rmean = roll_meanl(SWI_001,3)) %>% 
  filter(between(date,2,4)) %>% 
  select(-date)

我想要变量 SWI_001 的每第三行的滚动平均值。带有数据的新变量应该是 roll_mean1。

但我不知道如何正确过滤它。

我的数据框 (w) 看起来像这样,但是总共有 255 行和近 50 列:

           Date ASS_SUB ASS_TOP SWI_001 SWI_005 SWI_010 SWI_100 B1_005 B1_015 B1_025 B1_035 B1_045 B1_055 B1_065
  1: 06.11.2018   17.37   14.16   15.54      NA   15.57      NA     NA     NA     NA     NA     NA     NA     NA
  2: 07.11.2018   17.32   13.90   15.21      NA   15.51      NA   14.4   14.8   14.8   14.8   14.8   14.8   14.8
  3: 08.11.2018   17.29   13.77   14.75      NA   15.39      NA   14.2   14.8   14.8   14.8   14.8   14.8   14.8
  4: 09.11.2018   17.27   13.64   15.05      NA   15.38      NA   14.0   14.8   14.8   14.8   14.8   14.8   14.8
  5: 10.11.2018   17.24   13.64   14.89      NA   15.30      NA   13.9   14.8   14.8   14.8   14.8   14.8   14.8
 ---                                                                                                            

最后,我需要的不仅仅是一列的滚动均值,但一开始我很高兴能朝正确的方向推动。

解决方法

有很多不同的方法来做到这一点:

  • 您可以使用 zoo 包 (rollmean) 中的滚动均值/最大值/中位数函数
  • MovingAverages 中使用 TTR
  • ma中使用forecast

另见此处:Calculating moving average

对于下一个问题,如果您可以使用 dput() 将数据包含在您列出的代码中,那就太好了 - 我尝试快速重新创建它:

library(tidyverse)
tibble::tribble(
  ~Date,~ASS_SUB,~ASS_TOP,~SWI_001,~SWI_005,~SWI_010,~SWI_100,~B1_005,~B1_015,~B1_025,~B1_035,~B1_045,~B1_055,~B1_065,"06.11.2018",17.37,14.16,15.54,NA,15.57,"07.11.2018",17.32,13.90,15.21,15.51,14.4,14.8,"08.11.2018",17.29,13.77,14.75,15.39,14.2,"09.11.2018",17.27,13.64,15.05,15.38,14.0,"10.11.2018",17.24,14.89,15.30,13.9,14.8
) -> w

对于您的示例,我将使用 rollmean 包中的 zoo。我们使用 fill = NA 选项来指示没有 3 个值(一个之前,一个之后)的值应该是 NA。这意味着您不必过滤数据。您当然可以修改它 - 使用 ?na.fill 查看更多信息。

library(zoo)
w %>% 
  mutate(rmean = rollmean(SWI_001,3,fill = NA))

如果要将其应用于大量列,可以使用 across() 包中的 dplyr 命令:

w %>% 
  mutate(across(.cols = c(SWI_001,SWI_010),.fns = ~rollmean(.,fill = NA),.names = "{.col}_rmean"))

甚至对于所有数字列:

w %>% 
  mutate(across(.cols = where(is.numeric),.names = "{.col}_rmean"))

关于过滤的更多信息:

我不确定 1:2: 等是您的 Date 变量(下面的案例 1)还是只是行号(案例 2)的一部分。但无论如何,我建议使用以下任一方法将列转换为 Date 格式:

案例 1:

w %>% 
  mutate(Date = gsub("[0-9]: ","",Date),Date = as.Date(Date,format = "%d.%m.%Y"))

情况 2:

w %>% 
  mutate(Date = as.Date(Date,format = "%d.%m.%Y"))

一旦你有了这个,你就可以轻松地使用(并从上面组合):

w %>% 
  mutate(Date = gsub("[0-9]: ",format = "%d.%m.%Y")) %>%
  mutate(across(.cols = c(SWI_001,.names = "{.col}_rmean")) %>% 
  filter(between(Date,as.Date("2018-11-07"),as.Date("2018-11-09")))