182天平均滚动

时间:2020-01-08 02:24:50

标签: r loops average rolling-computation

我有一个具有多个站点和采样年的数据集,并为一年中的每一天评分。例如,SiteA有40年的数据,每天都有一个值,采样年定义为Sampling.Year。让我们感到困惑的采样年是7月至6月,因此采用2016-2017年的形式。 例如:

SiteName Sampling.Year   Date    Score 
A        2015-2016               1  
A        2015-2016               5  
A        2015-2016               2 
A        2016-2017               3 
A        2016-2017               12 
A        2016-2017               6 
B        2015-2016               9 
B        2015-2016               2 
B        2015-2016               1 
B        2016-2017               4 
B        2016-2017               1 
B        2016-2017               7

我想对这些数据应用182天的滚动平均值,以找到每个站点/Sampling.Year组合的最高得分(182天平均值)。结果将是,例如:

Site Sampling.Year   MaxAve StartDate
A    2016-2017       7.5    01/10/2016 
A    2017-2018       6.0    12/12/2017 
B    2016-2017       2.3    13/11/2016
B    2017-2018       4.2    09/09/2017 

我在这里保存了一个样本数据集: Sample data。 我想按照这种方式使用循环代码(因为我是新手,我不确定是否有更好的方法),但这是站点和年份的组合,我觉得很棘手。理想情况下,我希望能够将移动平均值导出为带有每个窗口的开始和结束日期(或至少开始日期)的新数据框,以便我们可以根据当时的天气情况进行检查。

Moving_Average_Function <- function(arr, n=182){
  res = arr
  for(i in n:length(arr)){
    res[i] = mean(arr[(i-n+1):i])
  }
  res
}

预先感谢

2 个答案:

答案 0 :(得分:2)

如果愿意使用外部库,则可以使用dplyr软件包中的group_by()和RcppRoll软件包中的roll_mean()函数。 RcppRoll具有一组快速灵活的功能,用于计算移动平均值。

我也倾向于将您的DATE列转换为日期类,以便其排列顺畅。

library(dplyr)  # I would typically use library(tidyverse) to load both dplyr and tidyr (among other related packages)
library(tidyr)
library(lubridate)
library(RcppRoll)

my_data <- data.table::fread("DailyScore.csv")  # easy way to load a data frame from file

my_data2 <- my_data %>%
      mutate(DATE = dmy(DATE)) %>% # Converting to Date format
      pivot_longer(H1:T2, 
                   names_to = "Sensor",
                   values_to = "data"
                   )  %>% # convert column names to data
      group_by(STATION, Sensor) %>%  # so you don't average by site.
      arrange(STATION, DATE) %>%  # to be sure you are in order for the rolling mean 
                                  #  The STATION argument isn't necessary, but helps for display
      mutate(Mean_182 = roll_meanr(data, 182)) %>%  # New column with your rolling mean
      pivot_wider(names_from = Sensor, values_from = c(data, Mean_182))  # converts back to original "wide" format

my_data2[180:195,]

# # A tibble: 16 x 14
# # Groups:   STATION [1]
# STATION SITENAME Sampling.Year DATE       data_H1  data_I1 data_H2 data_P2 data_T2 Mean_182_H1
# <chr>   <chr>    <chr>         <date>       <dbl>    <dbl>   <dbl>   <dbl>   <dbl>       <dbl>
#       1 Site A  Site A   1979-1980     1980-06-28    2.85 1.06e- 9    2.10   0.762    2.85       NA   
# 2 Site A  Site A   1979-1980     1980-06-29    2.79 1.62e-12    2.06   0.744    2.79       NA   
# 3 Site A  Site A   1979-1980     1980-06-30    2.75 1.00e-11    2.04   0.732    2.75        2.70
# 4 Site A  Site A   1980-1981     1980-07-01    2.72 1.00e-11    2.01   0.724    2.72        2.71
# 5 Site A  Site A   1980-1981     1980-07-02    2.70 1.00e-11    2.00   0.720    2.70        2.73
# 6 Site A  Site A   1980-1981     1980-07-03    2.68 1.00e-11    1.98   0.718    2.68        2.74
# 7 Site A  Site A   1980-1981     1980-07-04    2.67 1.00e-11    1.97   0.719    2.67        2.75
# 8 Site A  Site A   1980-1981     1980-07-05    2.65 1.11e- 9    1.95   0.708    2.65        2.76
# 9 Site A  Site A   1980-1981     1980-07-06    2.62 2.77e-10    1.93   0.703    2.62        2.76
# 10 Site A  Site A   1980-1981     1980-07-07    2.60 3.18e-12    1.92   0.700    2.60        2.77
# 11 Site A  Site A   1980-1981     1980-07-08    2.59 1.00e-11    1.90   0.701    2.59        2.79
# 12 Site A  Site A   1980-1981     1980-07-09    2.59 1.00e-11    1.89   0.706    2.59        2.80
# 13 Site A  Site A   1980-1981     1980-07-10    2.59 1.00e-11    1.89   0.713    2.59        2.81
# 14 Site A  Site A   1980-1981     1980-07-11    2.59 1.00e-11    1.88   0.722    2.59        2.82
# 15 Site A  Site A   1980-1981     1980-07-12    2.60 1.00e-11    1.88   0.731    2.60        2.83
# 16 Site A  Site A   1980-1981     1980-07-13    2.60 1.00e-11    1.87   0.741    2.60        2.84
# # ... with 4 more variables: Mean_182_I1 <dbl>, Mean_182_H2 <dbl>, Mean_182_P2 <dbl>, Mean_182_T2 <dbl>

请记住一些事情,这将影响您的设置方式。

  1. 通常,滚动平均值没有完整的数据集时,它们将返回NA。因此,以182天的平均值计算,您将在获得第一个完整平均值之前获得一系列181 NA。

  2. 您需要弄清楚如何处理零件的翻滚-尤其是长期滚动平均值的情况下,如果您不想混合采样年,则大约有半年的时间没有数据。

答案 1 :(得分:1)

对于这样的操作,使用循环会非常低效。您可以使用一些专用功能,使您可以按组执行此操作,并使用zoo::rollmean获得滚动平均值。

library(dplyr)

DailyScore %>% 
  group_by(SITENAME, Sampling.Year) %>% 
  summarise(max_average = max(zoo::rollmean(Score, 182)))
相关问题