You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在2001-2006与2006-2011两个时间窗口实现两年移动平均?

问题描述

原始数据集

Year   Pct
  2011   -97%
  2010   -95%
  2009   -90%
  2008   -72%
  2007   -40%
  2006    NA
  2005    47%
  2004    71%
  2003    -25%
  2002    116%
  2001    -5%

需求说明

需要分别在2001-2006和2006-2011两个独立时间窗口内计算两年移动平均,预期计算结果如下:

Year    Pct   MovAvg
  2011   -97%   (-97  +  -95)/2
  2010   -95%   (-95  +  -90)/2
  2009   -90%   (-90  +  -72)/2
  2008   -72%   (-72  +  -40)/2
  2007   -40%   NA 
  2006    NA    NA
  2005    47%   (47  +  71)/2
  2004    71%   (71  + -25)/2
  2003    -25%  (-25 + 116 )/2
  2002    116%  (116 - 5)/2
  2001    -5%   NA

已知可用apply(embed(x, k), 1, mean)实现两年滚动平均,但不清楚如何在上述两个独立窗口中应用该逻辑,寻求解决方法。


解决方法

核心思路是拆分数据集到两个目标时间窗口,分别计算滚动平均后再合并结果,以下是具体实现步骤:

步骤1:数据预处理

先把百分比格式的数值转为纯数字,方便计算:

# 假设原始数据存储在名为df的数据框中
df$Pct_num <- as.numeric(sub("%", "", df$Pct))

步骤2:分窗口计算移动平均

按年份升序排序后,分别处理两个窗口,注意移动平均的计算逻辑是当前年份值 + 前一年份值的平均:

# 按年份升序排列数据
df_sorted <- df[order(df$Year), ]

# 处理2001-2006窗口
window1 <- df_sorted[df_sorted$Year >= 2001 & df_sorted$Year <= 2006, ]
window1$MovAvg <- c(NA, apply(embed(window1$Pct_num, 2), 1, mean))

# 处理2006-2011窗口
window2 <- df_sorted[df_sorted$Year >= 2006 & df_sorted$Year <= 2011, ]
window2$MovAvg <- c(NA, apply(embed(window2$Pct_num, 2), 1, mean))

# 合并窗口结果,去掉重复的2006年数据,再按原年份降序排列
result <- rbind(window1, window2[window2$Year != 2006, ])
result <- result[order(-result$Year), ]

# 把移动平均转为预期的表达式格式(可选)
result$MovAvg_expr <- ifelse(is.na(result$MovAvg), "NA", 
                            paste0("(", result$Pct_num, " + ", lag(result$Pct_num), ")/2"))

步骤3:整理最终输出

提取需要的列,匹配预期格式:

final_output <- result[, c("Year", "Pct", "MovAvg_expr")]
colnames(final_output)[3] <- "MovAvg"
print(final_output, row.names = FALSE)

更简洁的dplyr实现

如果熟悉dplyr和zoo包,可以用分组方式高效处理:

library(dplyr)
library(zoo)

df %>%
  # 转换百分比为数值
  mutate(Pct_num = as.numeric(sub("%", "", Pct))) %>%
  # 按年份升序排列
  arrange(Year) %>%
  # 标记所属窗口
  mutate(window = case_when(
    Year >=2001 & Year <=2006 ~ "window1",
    Year >=2006 & Year <=2011 ~ "window2"
  )) %>%
  # 按窗口分组计算移动平均
  group_by(window) %>%
  mutate(MovAvg = ifelse(is.na(Pct_num), NA, lag(rollmean(Pct_num, k=2, fill=NA, align="right")))) %>%
  ungroup() %>%
  # 生成表达式格式的移动平均
  mutate(MovAvg_expr = ifelse(is.na(MovAvg), "NA", 
                            paste0("(", Pct_num, " + ", lag(Pct_num), ")/2"))) %>%
  # 按年份降序排列,整理输出列
  arrange(-Year) %>%
  select(Year, Pct, MovAvg_expr) %>%
  rename(MovAvg = MovAvg_expr)

注:使用rollmean需要先安装zoo包:install.packages("zoo")


内容的提问来源于stack exchange,提问作者Ahir Bhairav Orai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:50:14