基于月度均值填充时间序列缺失值(NA)的实现方法问询
用对应月份均值填充时间序列缺失值
这是个很常见的时间序列缺失值填充需求,用对应月份的季节均值来填充非常合理,下面给你两种实现方式,分别用base R和tidyverse工具包,你可以根据自己的习惯选择:
方法一:Base R 实现
不需要额外安装包,直接用R原生函数即可:
# 先构造完整的数据框 df <- data.frame( Date = seq(as.Date("1993-12-01"), as.Date("2005-05-01"), by = "1 month"), value = c(2.20000, 0.70000, 2.80000, 0.80000,1.20000, 1.50000, 0.90000 , NA, 0.80000, 1.70000, 2.40000, 1.60000, 4.00000, 4.40000, 2.50000, 1.10000, 2.40000, 1.10000, 3.70000, 6.40000, 7.00000, 2.90000, 3.00000, 3.60000, 4.90000, NA, 4.90000, 0.70000, 0.3000, 0.70000 ,0.37000,0.20000, 0.05000, 0.35000, 0.05000, 2.50000, 0.08000, 0.12000, 2.53000, 2.49000, 2.04000, 2.92000, 0.27000, 0.33000, 0.10000, 0.36000, 2.32000, 0.1900, 0.2300, 0.18000, 0.28000, 0.19500, 0.07300, 0.65000,0.30000) ) # 从日期中提取月份(格式为两位字符串,比如"07"代表7月) df$month <- format(df$Date, "%m") # 按月份分组计算非缺失值的均值 monthly_means <- tapply(df$value, df$month, mean, na.rm = TRUE) # 填充缺失值:将NA替换为对应月份的均值 df$value_filled <- ifelse(is.na(df$value), monthly_means[df$month], df$value)
关键步骤说明:
format(df$Date, "%m"):从日期列中提取月份信息,确保同月份的记录被分到同一组tapply(..., mean, na.rm = TRUE):按月份分组计算均值,na.rm=TRUE会自动忽略组内的NA值ifelse():判断每个值是否为NA,是则替换为对应月份的均值,否则保留原值
方法二:Tidyverse 实现
用dplyr做数据分组处理,lubridate简化日期操作,代码更直观易读:
# 先安装并加载所需包(如果没安装过的话) # install.packages(c("dplyr", "lubridate")) library(dplyr) library(lubridate) # 构造数据框(和base R部分一致) df <- data.frame( Date = seq(as.Date("1993-12-01"), as.Date("2005-05-01"), by = "1 month"), value = c(2.20000, 0.70000, 2.80000, 0.80000,1.20000, 1.50000, 0.90000 , NA, 0.80000, 1.70000, 2.40000, 1.60000, 4.00000, 4.40000, 2.50000, 1.10000, 2.40000, 1.10000, 3.70000, 6.40000, 7.00000, 2.90000, 3.00000, 3.60000, 4.90000, NA, 4.90000, 0.70000, 0.3000, 0.70000 ,0.37000,0.20000, 0.05000, 0.35000, 0.05000, 2.50000, 0.08000, 0.12000, 2.53000, 2.49000, 2.04000, 2.92000, 0.27000, 0.33000, 0.10000, 0.36000, 2.32000, 0.1900, 0.2300, 0.18000, 0.28000, 0.19500, 0.07300, 0.65000,0.30000) ) # 数据管道操作:提取月份 -> 分组 -> 填充缺失值 df_filled <- df %>% mutate(month = month(Date)) %>% # 用lubridate提取月份(返回1-12的数字) group_by(month) %>% # 按月份分组 mutate( value_filled = ifelse( is.na(value), mean(value, na.rm = TRUE), value ) ) %>% ungroup() # 取消分组
关键步骤说明:
lubridate::month(Date):直接返回日期对应的月份数字(1-12),比format()更简洁dplyr的管道操作%>%:把数据处理步骤串联起来,逻辑更清晰- 分组后计算组内均值并填充,和base R逻辑一致,但代码可读性更强
注意事项
如果某个月份的所有值都是NA,mean(..., na.rm=TRUE)会返回NaN,这种情况你可以根据需求调整,比如改用全局均值或者相邻月份的均值来填充,但根据你的描述,序列只有少量缺失,这种极端情况应该不会出现。
内容的提问来源于stack exchange,提问作者Vasker Sharma
相关产品推荐
相关产品推荐

