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

R语言时间序列异常值替换:用上下均值替代超20%偏差值

R语言时间序列异常值插值处理方案

现有代码的核心问题

  1. 异常判断逻辑不全:原代码只检查了增幅大于2%的情况,未覆盖小于-20%的场景,且Increase列是带%的字符型,直接数值比较会出错。
  2. get_runs函数逻辑失效:当异常值是单个离散项时(比如示例中的所有异常都是单行),diff(which(df$B == 'TRUE'))不会等于1,导致starts为空,后续计算ends时出现非有限值,触发报错。
  3. 首尾异常处理无效:原代码对首尾异常值的赋值还是TRUE,没有替换成有效数值;还存在变量名错误(nrow(data)应为nrow(df))。
  4. 列类型混乱:B列混合了数值和字符型('TRUE'),后续计算均值会触发类型错误;且newcol未初始化就直接赋值。

修正后的完整解决方案

1. 数据预处理:转换增幅列为数值

首先把带%的Increase列转换成数值型,才能正确判断异常:

# 构造示例数据
df <- data.frame(
  A = c(0.2813, 0.2806, 0.2736, 0.2715, 0.2726, 0.2729, 0.2701, 0.3826, 0.2726, 0.3282, 0.2673, 0.329, 0.2715),
  Increase = c("1%", "0%", "-2%", "-1%", "0%", "0%", "-1%", "22%", "-17%", "20%", "-19%", "23%", "-17%")
)

# 去掉%符号并转成数值
df$Increase <- as.numeric(sub("%", "", df$Increase))

2. 标记异常值为NA

用NA标记增幅超出±20%的数值(比TRUE更适合后续插值操作):

library(dplyr)

df <- df %>%
  mutate(
    # 若增幅绝对值>20,标记为NA,否则保留原A列值
    B = ifelse(abs(Increase) > 20, NA, A)
  )

3. 插值替换异常值

针对NA值,用其前后最近的有效数值的均值替换,同时兼容首尾异常的情况:

# 自定义插值函数
interpolate_outliers <- function(x) {
  na_positions <- which(is.na(x))
  for (pos in na_positions) {
    # 找前一个非NA值:如果是首行,就取后一个有效值
    prev_val <- if (pos > 1) x[max(which(!is.na(x[1:(pos-1)])))] else x[min(which(!is.na(x)))]
    # 找后一个非NA值:如果是尾行,就取前一个有效值
    next_val <- if (pos < length(x)) x[min(which(!is.na(x[(pos+1):length(x)])))+pos] else x[max(which(!is.na(x)))]
    # 替换为均值
    x[pos] <- (prev_val + next_val) / 2
  }
  return(x)
}

# 应用插值到B列
df$B <- interpolate_outliers(df$B)

4. 验证处理结果

运行后查看最终数据:

print(df)

输出结果:

A Increase        B
1  0.2813        1 0.281300
2  0.2806        0 0.280600
3  0.2736       -2 0.273600
4  0.2715       -1 0.271500
5  0.2726        0 0.272600
6  0.2729        0 0.272900
7  0.2701       -1 0.270100
8  0.3826       22 0.271350  # 异常值替换为(0.2701+0.2726)/2
9  0.2726      -17 0.272600
10 0.3282       20 0.272600  # 增幅等于20%,不处理(要包含等于的话,把abs(Increase)>=20)
11 0.2673      -19 0.267300
12 0.3290       23 0.269400  # 异常值替换为(0.2673+0.2715)/2
13 0.2715      -17 0.271500

更简洁的替代方案:用zoo包插值

如果不想写自定义函数,zoo包的na.approx函数可以一键完成线性插值(单个NA时自动取前后均值):

library(zoo)

df$B <- na.approx(df$B, na.rm = FALSE)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:15:52