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

用2-3周移动平均值替换时间序列中的异常降雨量值

用2-3周移动平均值替换时间序列中的异常降雨量值

下面是一套完整的实现方案,从异常值识别到替换全流程:

1. 自动识别异常值

先通过IQR方法标记异常值(比手动设阈值更通用,适合批量数据):

# 计算四分位距范围
q1 <- quantile(tbl$rainfall, 0.25)
q3 <- quantile(tbl$rainfall, 0.75)
iqr <- q3 - q1
upper_bound <- q3 + 1.5*iqr  # 降雨量不会为负,无需设置下限

# 标记异常行
tbl <- tbl %>%
  mutate(is_outlier = rainfall > upper_bound)

2. 计算不含异常值的移动平均值

重点:计算移动平均时要排除异常值,避免被异常值带偏。这里用3周中心窗口(当前周±1周),如果要2周的话调整窗口范围即可:

方法一:用slider包(灵活,支持任意窗口)

先安装slider包(如果没装),然后计算:

# install.packages("slider")
library(slider)

tbl <- tbl %>%
  mutate(rolling_mean_3w = slide_dbl(
    row_number(),
    .f = function(i) {
      # 划定窗口范围:当前行前后1行
      window <- max(1, i-1):min(nrow(tbl), i+1)
      # 取窗口内非异常值的平均值
      mean(tbl$rainfall[window][!tbl$is_outlier[window]], na.rm = TRUE)
    }
  ))

方法二:手动用lag/lead计算(无需额外包)

如果不想装新包,直接用dplyr的函数手动实现:

tbl <- tbl %>%
  mutate(
    # 收集当前、前1、后1周的降雨量,排除异常值
    window_vals = pmap(list(lag(rainfall), rainfall, lead(rainfall)), 
                       function(x,y,z) c(x,y,z)[!c(lag(is_outlier), is_outlier, lead(is_outlier))]),
    # 计算窗口平均值
    rolling_mean_3w = map_dbl(window_vals, mean, na.rm = TRUE)
  ) %>%
  select(-window_vals)  # 删除临时列

3. 替换异常值

把标记为异常的降雨量替换成计算好的移动平均值:

tbl <- tbl %>%
  mutate(rainfall_clean = ifelse(is_outlier, rolling_mean_3w, rainfall))

完整可运行代码

把所有步骤整合,直接复制就能跑:

library(tidyverse)
library(lubridate)
library(slider)  # 用手动方法可注释此行

# 原始数据
week <- c("10-03-2021", "10-10-2021", "10-17-2021", "10-24-2021", "10-31-2021", "11-6-2021", "11-13-2021", "11-20-2021", "11-27-2021")
rainfall <- c(11, 12, 13, 1010, 1000, 16, 16, 18, 15)

tbl <- tibble(week = mdy(week), 
              rainfall = rainfall)

# 1. 标记异常值
q1 <- quantile(tbl$rainfall, 0.25)
q3 <- quantile(tbl$rainfall, 0.75)
iqr <- q3 - q1
upper_bound <- q3 + 1.5*iqr

tbl <- tbl %>%
  mutate(is_outlier = rainfall > upper_bound)

# 2. 计算3周移动平均(排除异常值)
tbl <- tbl %>%
  mutate(rolling_mean_3w = slide_dbl(
    row_number(),
    .f = function(i) {
      window <- max(1, i-1):min(nrow(tbl), i+1)
      mean(tbl$rainfall[window][!tbl$is_outlier[window]], na.rm = TRUE)
    }
  ))

# 3. 替换异常值
tbl <- tbl %>%
  mutate(rainfall_clean = ifelse(is_outlier, rolling_mean_3w, rainfall))

# 查看结果
print(tbl)

运行后,示例中的1010会被替换成13(前后仅前一周的13是正常值),1000会被替换成16(前后仅后一周的16是正常值),完全符合合理替换的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:07:54