python - 修改时间序列数据中传感器故障引起的异常值

标签 python pandas time-series outliers anomaly-detection

我正在处理从传感器以 5 分钟间隔收集的时间序列数据。不幸的是,在某些情况下,测量值(以瓦为单位的光伏发电量)突然为 0 或非常高之前和之后的值是正确的:

enter image description here

我的目标是识别这些“异常值”并(在第二步中)计算前一个值和下一个值的平均值以固定测量值。到目前为止,我已经尝试了两种方法,但收到了许多不是测量误差的“异常值”。因此,我正在寻找更好的方法。

尝试 1:使用 IQR 进行经典异常值检测 Source

def updateOutliersIQR(group):
  Q1 = group.yield.quantile(0.25)
  Q3 = group.yield.quantile(0.75)
  IQR = Q3 - Q1
  outliers = (group.yield < (Q1 - 1.5 * IQR)) | (group.yield > (Q3 + 1.5 * IQR))
  print(outliers[outliers == True]) 

# calling the function on a per-day level
df.groupby(df.index.date).apply(updateOutliers)

尝试 2:核密度估计 Source

def updateOutliersKDE(group):
  a = 0.9
  r = group.yield.rolling(3, min_periods=1, win_type='parzen').sum()
  n = r.max()
  outliers = (r > n*a)
  print(outliers[outliers == True]) 

# calling the function on a per-day level
df.groupby(df.index.date).apply(updateOutliers)

尝试 3:中值滤波器 Source (根据 Jonnor 的建议)

def median_filter(num_std=3):
  def _median_filter(x):
    _median = np.median(x)
    _std = np.std(x)
    s = x[-3]
    if (s >= _median - num_std * _std and s <= _median + num_std * _std):
      return s
    else:
      return _median
  return _median_filter

# calling the function
df.yield.rolling(5, center=True).apply(median_filter(2), raw=True)

编辑:通过尝试 3、窗口为 5、标准值为 3,它最终捕获了大量异常值,但也会降低其他(无故障)传感器测量的准确性: enter image description here

是否有更好的方法来检测所描述的“异常值”或在偶尔传感器测量问题的时间序列数据中执行平滑?

最佳答案

您的异常值是异常的,因为

  • 这些值与其周围的值偏差很大
  • 从一个时间步长到另一个时间步长的值变化非常快

因此需要一个过滤器,它可以查看短时间上下文来过滤掉这些内容。

最简单、最有效的方法之一是 median filter .

filtered = pandas.rolling_median(df, window=5)

窗口越长,过滤器越强。

另一种选择是低通滤波器。尽管设置适当的截止频率可能会比较困难,但它会给信号带来平滑度。

当然也可以创建更多自定义过滤器。例如,计算一阶差分,并拒绝高于特定阈值的更改。您可以绘制差异的直方图来确定阈值。将它们标记为缺失 (NaN),然后使用中位数/均值估算缺失。

如果您的目标是异常检测,您还可以使用自动编码器。我预计光伏输出将具有非常强劲的每日模式。因此,根据日常序列对其进行训练应该会效果很好(前提是您有足够的数据)。这比简单的过滤器复杂得多,但优点是还能够检测许多其他类型的异常,而不仅仅是此处识别的模式。

关于python - 修改时间序列数据中传感器故障引起的异常值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62473007/

相关文章:

python - 在 Python 中打开 excel 文件时出现错误

python - SSLError : unable to get local issuer certificate (_ssl. c:1076)

python - 在写入 CSV 文件时从中读取

python - 为 joyplot 设置 x 轴标签

python - 如何轻松地在列表中找到具有给定类属性的类实例?

python - 如何使用相对路径使用 pandas 在 data_folder 中打开我的文件?

python - Pandas pythonic 方式从 pd.Series 中提取值和索引作为元组

r - 使用R将时间序列中的事件分组

mysql - 如何在sql中逐周显示

python - 如何从数据框中将多个级别的聚合总和放入时间序列列中