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

R语言实现分时段滑动平均填补气象数据缺失值

嘿,我明白你的问题了!之前用rollapply之类的函数没搞定,核心原因是没抓住「只取对应时刻数据」这个关键点——你需要先把每天同一时段的观测归为一组,再在每组内做滑动平均,而不是对整个连续时间序列用大窗口。我给你分两步解决:先搞定示例,再扩展到你实际的30分钟14天滑动平均需求。

先解决你的示例问题

你的示例要求用6小时滑动平均补缺,偶数时段用偶数数据填补,奇数时段用奇数数据填补。我们先给每个小时打上「奇偶时段标识」,再分组处理:

library(dplyr)
library(zoo)

# 你的示例数据
data <- data.frame(
  hour = c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23),
  values = c(1,3,1,3,1,3,1,3,1,NA,1,3,1,3,NA,3,1,3,1,3,1,3,1,3)
)

# 第一步:给每个小时打上奇偶时段标识(0=偶数时段,1=奇数时段)
data <- data %>%
  mutate(period_id = hour %% 2)

# 第二步:定义补缺函数,包含最小有效数据点判断
fill_with_rollmean <- function(x, window_width, min_valid) {
  rollapply(
    x,
    width = window_width,
    align = "center",  # 中心对齐,取当前点前后的同时段数据
    FUN = function(y) {
      valid_count <- sum(!is.na(y))
      # 只有有效数据数达标才填补,否则返回NA
      if (valid_count >= min_valid) mean(y, na.rm = TRUE) else NA
    },
    fill = NA  # 首尾超出窗口的部分保持NA
  )
}

# 第三步:按时段分组,应用补缺函数
data_filled <- data %>%
  group_by(period_id) %>%
  # 窗口宽度3=当前点+前后1个同时段数据(对应6小时跨度),最小有效数设为2
  mutate(gap_fill = fill_with_rollmean(values, window_width = 3, min_valid = 2)) %>%
  ungroup()

# 查看结果:hour=9的NA会被补为3,hour=14的NA会被补为1,符合你的预期
print(data_filled)
扩展到30分钟分辨率14天滑动平均需求

针对你实际的数月30分钟气象数据,核心思路是给每个30分钟时段打唯一标识(比如每天的第1到第48个30分钟),然后按标识分组,用14天的同时段数据做滑动平均:

library(dplyr)
library(zoo)
library(lubridate)

# 假设你的数据框是df,包含datetime(POSIXct格式)和values列
# 第一步:给每个30分钟时段打唯一标识(1-48,对应每天的00:00到23:30)
df <- df %>%
  mutate(
    period_id = (hour(datetime) * 2) + ifelse(minute(datetime) == 30, 2, 1)
  )

# 第二步:定义14天滑动平均补缺函数
fill_14day_rollmean <- function(x, window_width = 14, min_valid = 7) {
  rollapply(
    x,
    width = window_width,  # 对应14天的同时段数据
    align = "center",      # 取当前天前后各6天+当天,共14个数据
    FUN = function(y) {
      valid_count <- sum(!is.na(y))
      if (valid_count >= min_valid) mean(y, na.rm = TRUE) else NA
    },
    fill = NA  # 首尾超出窗口的部分保持NA
  )
}

# 第三步:按时段分组补缺
df_filled <- df %>%
  group_by(period_id) %>%
  mutate(values_filled = fill_14day_rollmean(values)) %>%
  ungroup()
关键注意事项
  • 时间序列补全:如果你的原始数据有缺失的日期/时段,先要用tidyr::complete(datetime = seq(min(datetime), max(datetime), by = "30 mins"))补全为连续的时间序列,否则分组后的序列会有间隔,滑动窗口会取到非连续的日期数据。
  • 窗口调整:如果你要的是「前后7天」(共15个数据点:当天+前7天+后7天),把window_width改成15即可,align="center"会自动匹配前后7个数据。
  • 最小有效数:根据你的需求调整min_valid参数,比如要求至少10个有效数据才填补,就设为10。

内容的提问来源于stack exchange,提问作者jls

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:40:54