时间序列平台型离群点识别:非等值平台检测问题及方案问询
识别时间序列中近零斜率平台区域的方法与库
针对你用np.diff无法识别非完全等值近零斜率平台的问题,以下是几种实用的方法和可用库:
1. 滑动窗口斜率阈值法(Numpy/Scipy实现)
直接针对斜率近零这个平台核心特征,用滑动窗口计算局部线性拟合的斜率,筛选斜率绝对值低于阈值且长度达标的连续区间:
import numpy as np from scipy.stats import linregress def find_plateaus_slope_window(F, min_length=5, slope_threshold=0.01, window_size=11): n = len(F) is_plateau = np.zeros(n, dtype=bool) for i in range(n - window_size + 1): window = F[i:i+window_size] x = np.arange(window_size) slope, _, _, _, _ = linregress(x, window) if abs(slope) <= slope_threshold: is_plateau[i:i+window_size] = True # 提取连续达标区间 diff = np.diff(np.concatenate(([0], is_plateau.astype(int), [0]))) starts = np.where(diff == 1)[0] ends = np.where(diff == -1)[0] return np.array([[s, e] for s, e in zip(starts, ends) if e - s >= min_length])
2. Pandas Rolling窗口统计
利用Pandas的滚动窗口功能,结合数据波动(标准差)和斜率双重条件筛选平台,更鲁棒:
import pandas as pd import numpy as np from scipy.stats import linregress def rolling_slope(window): x = np.arange(len(window)) return linregress(x, window)[0] def find_plateaus_pandas(series, min_length=5, slope_tol=0.01, std_tol=0.1, window=11): rolling_slopes = series.rolling(window=window).apply(rolling_slope, raw=True) rolling_std = series.rolling(window=window).std() # 标记符合条件的点 is_plateau = (abs(rolling_slopes) <= slope_tol) & (rolling_std <= std_tol) is_plateau = is_plateau.fillna(False) # 提取连续区间 diff = np.diff(np.concatenate(([0], is_plateau.astype(int), [0]))) starts = np.where(diff == 1)[0] ends = np.where(diff == -1)[0] return np.array([[s, e] for s, e in zip(starts, ends) if e - s >= min_length])
3. Scipy信号处理工具
用Scipy的信号平滑函数先降噪,再通过一阶导数绝对值筛选近零斜率区域,适合噪声较多的时间序列:
import numpy as np from scipy.ndimage import uniform_filter1d def find_plateaus_scipy(F, min_length=5, slope_tol=0.01, smoothing=11): smoothF = uniform_filter1d(F, size=smoothing) dF = np.gradient(smoothF) smooth_dF = uniform_filter1d(dF, size=smoothing) # 标记斜率近零的点 is_plateau = np.abs(smooth_dF) <= slope_tol # 提取连续区间 diff = np.diff(np.concatenate(([0], is_plateau.astype(int), [0]))) starts = np.where(diff == 1)[0] ends = np.where(diff == -1)[0] return np.array([[s, e] for s, e in zip(starts, ends) if e - s >= min_length])
4. 时间序列特征库Tsfresh
Tsfresh内置大量时间序列特征提取函数,可直接调用或自定义特征来检测平台:
- 利用内置特征:比如
longest_strike_below_mean(连续低于均值的最长段)、mean_abs_change(平均绝对变化率)等,筛选变化率极低的连续段 - 自定义特征:编写函数检测局部斜率近零的区间,结合Tsfresh的批量处理能力
对你现有代码的改进建议
你当前用二阶导数检测的思路可以调整为一阶导数近零(平台的核心是斜率为0,一阶导数直接反映斜率),同时替换区间检测逻辑,避免依赖np.diff(smalld2F)的突变检测,改用连续True段的提取方式(如上述代码中的diff方法),能更准确捕捉非完全等值的平台区域。
内容的提问来源于stack exchange,提问作者chan
相关产品推荐
相关产品推荐

