时间序列数据异常值高效去除方案求助
时间序列异常值精准识别与移除方案(R语言)
之前的全局统计类方法(箱线图IQR、performance包工具)未考虑时间序列的时序趋势/局部上下文,因此会误判末尾的趋势性高值为异常,同时可能因为全局统计范围覆盖了部分局部异常值而漏判。以下是针对性解决方案:
1. 滑动窗口局部IQR法(适配时序趋势)
基于每个数据点的局部时序窗口计算IQR阈值,既能识别局部异常,又不会误删趋势性增长的合法值,还可结合已知目标异常值强化识别:
library(dplyr) library(zoo) # 假设你的数据是包含date(日期列)和value(数值列)的data.frame # 若为ts对象,先转换:df <- data.frame(date = time(your_ts), value = as.numeric(your_ts)) # 设定滑动窗口大小(月度数据建议设为12,根据数据频率调整) window_size <- 12 df <- df %>% mutate( # 滚动计算窗口内的四分位数与IQR q1 = rollapply(value, width = window_size, FUN = quantile, probs = 0.25, fill = NA, align = "center"), q3 = rollapply(value, width = window_size, FUN = quantile, probs = 0.75, fill = NA, align = "center"), iqr = q3 - q1, lower = q1 - 1.5 * iqr, upper = q3 + 1.5 * iqr, # 标记异常:超出局部阈值 或 属于已知目标异常值 is_outlier = (value < lower | value > upper) | (value %in% c(21637, 19590, 21659, 200000)) ) # 筛选去除异常值 clean_df <- df %>% filter(!is_outlier)
2. 时序分解法(分离趋势/季节成分)
将时间序列分解为趋势、季节、残差成分,异常值通常体现在残差的极端波动中,避免趋势/季节因素干扰判断:
library(stats) # 分解时间序列(月度数据用加法模型,指数增长趋势用乘法模型type = "multiplicative") decomp <- decompose(your_ts, type = "additive") # 计算残差的IQR阈值 residuals <- decomp$random q1_resid <- quantile(residuals, 0.25, na.rm = TRUE) q3_resid <- quantile(residuals, 0.75, na.rm = TRUE) iqr_resid <- q3_resid - q1_resid lower_resid <- q1_resid - 1.5 * iqr_resid upper_resid <- q3_resid + 1.5 * iqr_resid # 标记异常:残差超出阈值 或 属于已知目标异常值 is_outlier <- (residuals < lower_resid | residuals > upper_resid) | (as.numeric(your_ts) %in% c(21637, 19590, 21659, 200000)) # 生成清洁后的时间序列 clean_ts <- your_ts[!is_outlier]
3. 精准定位法(针对已知异常值)
若已明确异常值的日期和数值,直接通过日期+值的组合精准定位并移除,完全避免误判:
library(dplyr) # 假设数据为含date和value的data.frame target_outliers <- df %>% filter( (date == as.Date("1993-06-01") & value == 21637) | (date == as.Date("1994-08-01") & value %in% c(19590, 21659)) | (date == as.Date("1995-03-01") & value == 200000) ) # 移除目标异常值 clean_df <- df %>% anti_join(target_outliers, by = c("date", "value"))
内容的提问来源于stack exchange,提问作者Tung
相关产品推荐
相关产品推荐

