如何计算无NA值的年日序循环7日中心滚动均值?
实现循环年日序的无NA值7日中心滚动均值
方法一:利用rollapply的circular参数(推荐)
zoo包的rollapply函数支持circular=TRUE参数,可直接处理循环序列的滚动计算,无需手动调整数据:
library(tidyverse) library(zoo) set.seed(321) aa <- data.frame( doy = seq(1,365,1), value = round(rnorm(365,30,5)) ) # 计算循环的7日中心滚动均值 bb <- aa %>% mutate(movingAVG = round(rollapply(value, width = 7, FUN = mean, align = 'center', circular = TRUE))) # 查看前6行结果 head(bb) #> doy value movingAVG #> 1 1 39 30 #> 2 2 26 30 #> 3 3 29 31 #> 4 4 29 31 #> 5 5 29 30 #> 6 6 31 31 # 查看后6行结果 tail(bb) #> doy value movingAVG #> 360 360 24 30 #> 361 361 38 29 #> 362 362 30 29 #> 363 363 20 28 #> 364 364 26 29 #> 365 365 29 30
原理说明
circular=TRUE会将输入的value序列视为循环结构:
- 当计算开头日期(如doy=1)的滚动均值时,窗口自动从序列末尾取doy=363、364、365的数据补全前3天;
- 当计算末尾日期(如doy=365)的滚动均值时,窗口自动从序列开头取doy=1、2、3的数据补全后3天;
- 最终每个日期都能得到完整的7日窗口均值,无NA值。
方法二:手动扩展数据实现循环逻辑
如果需要更直观地控制窗口数据,可通过扩展原始数据的方式实现:
library(tidyverse) library(zoo) set.seed(321) aa <- data.frame( doy = seq(1,365,1), value = round(rnorm(365,30,5)) ) # 扩展数据:开头添加原数据最后3行,结尾添加原数据最前3行 extended_aa <- bind_rows(tail(aa, 3), aa, head(aa, 3)) # 计算中心7日滚动均值 extended_aa <- extended_aa %>% mutate(movingAVG = round(rollmean(value, k = 7, align = 'center'))) # 截取中间365行,得到原日期对应的无NA结果 bb <- extended_aa %>% slice(4:(365+3)) # 验证结果(与方法一一致) head(bb) tail(bb)
原理说明
扩展数据后,原序列的首尾日期在新序列中处于中间位置,其滚动窗口会包含来自原序列另一端的补全数据,最终截取中间部分即可得到符合循环逻辑的完整结果。
内容的提问来源于stack exchange,提问作者tassones
相关产品推荐
相关产品推荐

