Статьи

R: Расчет скользящих или скользящих средних

Я играл с некоторыми данными временных рядов в R, и, поскольку между последовательными точками есть небольшая разница, я хотел сгладить данные путем вычисления скользящего среднего.

Я изо всех сил пытался найти встроенную функцию, чтобы сделать это, но наткнулся на пост в блоге Дидье Руидена, в котором описана следующая функция для выполнения работы:

1
mav <- function(x,n=5){filter(x,rep(1/n,n), sides=2)}

Я попытался подключить некоторые цифры, чтобы понять, как это работает:

1
2
3
4
5
6
> mav(c(4,5,4,6), 3)
Time Series:
Start = 1
End = 4
Frequency = 1
[1]       NA 4.333333 5.000000       NA

Здесь я пытался получить скользящее среднее, которое учитывало последние 3 числа, поэтому я ожидал получить только два числа назад — 4.333333 и 5 — и если бы были значения NA, я думал, что они будут в начале последовательность.

Фактически получается, что это то, что контролирует параметр ‘сторон’:

1
2
3
4
sides  
for convolution filters only. If sides = 1 the filter coefficients are for past values only; if sides = 2 they
are centred around lag 0. In this case the length of the filter should be odd, but if it is even, more of the
filter is forward in time than backward.

Таким образом, в нашей функции ‘mav’ скользящее среднее смотрит на обе стороны текущего значения, а не только на прошлые значения. Мы можем настроить это, чтобы получить поведение, которое мы хотим:

1
mav <- function(x,n=5){filter(x,rep(1/n,n), sides=1)}
1
2
3
4
5
6
> mav(c(4,5,4,6), 3)
Time Series:
Start = 1
End = 4
Frequency = 1
[1]       NA       NA 4.333333 5.000000

Значения NA раздражают любые графики, которые мы хотим сделать, поэтому давайте избавимся от них:

1
2
3
4
5
6
> na.omit(mav(c(4,5,4,6), 3))
Time Series:
Start = 3
End = 4
Frequency = 1
[1] 4.333333 5.000000

Добравшись до этого момента, я заметил, что Дидье ссылался на пакет zoo в комментариях, и у него есть встроенная функция, чтобы позаботиться обо всем этом:

1
2
3
> library(zoo)
> rollmean(c(4,5,4,6), 3)
[1] 4.333333 5.000000

Я также понял, что могу перечислить все функции в пакете с помощью функции ‘ls’, так что я буду сканировать список функций зоопарка в следующий раз, когда мне нужно будет сделать что-то связанное с временными рядами — вероятно, уже будет функция для этого!

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
> ls("package:zoo")
  [1] "as.Date"              "as.Date.numeric"      "as.Date.ts"         
  [4] "as.Date.yearmon"      "as.Date.yearqtr"      "as.yearmon"         
  [7] "as.yearmon.default"   "as.yearqtr"           "as.yearqtr.default" 
 [10] "as.zoo"               "as.zoo.default"       "as.zooreg"          
 [13] "as.zooreg.default"    "autoplot.zoo"         "cbind.zoo"          
 [16] "coredata"             "coredata.default"     "coredata<-"         
 [19] "facet_free"           "format.yearqtr"       "fortify.zoo"        
 [22] "frequency<-"          "ifelse.zoo"           "index"              
 [25] "index<-"              "index2char"           "is.regular"         
 [28] "is.zoo"               "make.par.list"        "MATCH"              
 [31] "MATCH.default"        "MATCH.times"          "median.zoo"         
 [34] "merge.zoo"            "na.aggregate"         "na.aggregate.default"
 [37] "na.approx"            "na.approx.default"    "na.fill"            
 [40] "na.fill.default"      "na.locf"              "na.locf.default"    
 [43] "na.spline"            "na.spline.default"    "na.StructTS"        
 [46] "na.trim"              "na.trim.default"      "na.trim.ts"         
 [49] "ORDER"                "ORDER.default"        "panel.lines.its"    
 [52] "panel.lines.tis"      "panel.lines.ts"       "panel.lines.zoo"    
 [55] "panel.plot.custom"    "panel.plot.default"   "panel.points.its"   
 [58] "panel.points.tis"     "panel.points.ts"      "panel.points.zoo"   
 [61] "panel.polygon.its"    "panel.polygon.tis"    "panel.polygon.ts"   
 [64] "panel.polygon.zoo"    "panel.rect.its"       "panel.rect.tis"     
 [67] "panel.rect.ts"        "panel.rect.zoo"       "panel.segments.its" 
 [70] "panel.segments.tis"   "panel.segments.ts"    "panel.segments.zoo" 
 [73] "panel.text.its"       "panel.text.tis"       "panel.text.ts"      
 [76] "panel.text.zoo"       "plot.zoo"             "quantile.zoo"       
 [79] "rbind.zoo"            "read.zoo"             "rev.zoo"            
 [82] "rollapply"            "rollapplyr"           "rollmax"            
 [85] "rollmax.default"      "rollmaxr"             "rollmean"           
 [88] "rollmean.default"     "rollmeanr"            "rollmedian"         
 [91] "rollmedian.default"   "rollmedianr"          "rollsum"            
 [94] "rollsum.default"      "rollsumr"             "scale_x_yearmon"    
 [97] "scale_x_yearqtr"      "scale_y_yearmon"      "scale_y_yearqtr"    
[100] "Sys.yearmon"          "Sys.yearqtr"          "time<-"             
[103] "write.zoo"            "xblocks"              "xblocks.default"    
[106] "xtfrm.zoo"            "yearmon"              "yearmon_trans"      
[109] "yearqtr"              "yearqtr_trans"        "zoo"                
[112] "zooreg"

Будьте общительны, делитесь!