如何检测时间序列数据帧中的异常值并将 "clean" 写入新数据帧

How to detect outliers in a timeseries dataframe and write the "clean" ones in a new dataframe

我真的是 Python 的新手(和一般的编程,hihi)我正在分析每 10 秒测量的 2 年气象数据,我总共有 12 个气象参数并且我创建了我的数据框 df,时间作为我的行索引,气象参数的名称作为列名。由于我不需要超粒度,我已将数据重新采样为每小时数据,因此数据框看起来像这样。

Time                G_DIFF  G_HOR     G_INCL     RAIN    RH   T_a    V_a    V_a_dir                 
2016-05-01 02:00:00 0.0 0.011111    0.000000    0.013333    100.0   9.128167    1.038944    175.378056
2016-05-01 03:00:00 0.0 0.200000    0.016667    0.020000    100.0   8.745833    1.636944    218.617500
2016-05-01 04:00:00 0.0 0.105556    0.013889    0.010000    100.0   8.295333    0.931000    232.873333

存在异常值,我可以通过滚动标准差和均值来消除它们将干净的数据写入另一个数据帧(tr,在下面的示例中)。

roll = df["T_a"].rolling(24,center = True) #24h window
mean, std = roll.mean(), roll.std()
cut = std*3
low, up = mean - cut, mean+cut
tr.loc[(df["T_a"] < low) | (df["T_a"] > up) | (df["T_a"].isna()), "outliers"] = df["T_a"]
tr.loc[(df["T_a"] >= low) & (df["T_a"] <= up), "T_a"] = df["T_a"]
tr.loc[tr["T_a"].isna(),"T_a"] = tr["T_a"].bfill() #to input a value when a datum is NaN

现在,正如我所说,这对一个列来说没问题,但我希望能够对 12 个列做到这一点,而且,我几乎可以肯定有一个更 pythonic 的方法来做到这一点。我想使用 for 循环应该是可行的,但到目前为止我没有尝试过。

谁能给我一些启发,好吗?非常感谢!!

有两种方法可以从时间序列数据中删除异常值,一种是计算百分位数,均值 std-dev 我认为您正在使用另一种方法是查看图表,因为有时数据传播会在视觉上提供更多信息.

我从事过某个地区的黄色出租车预测数据,所以基本上我有一个模型可以预测纽约出租车在哪个地区可以获得更多的客户。

因为我有一个时间间隔为 10 秒的时间序列数据,具有各种特征,如行程距离、速度、工作时间,其中一个是“总票价”,现在我还想从每一列中删除异常值,所以开始使用这样做的平均值和百分位数,

总票价是平均值,百分位数没有给出准确的阈值,

我的百分位数值:

0个百分位数值为-242.55// 第 10 个百分位值为 6.3// 20 个百分位数值为 7.8// 30 个百分位数值为 8.8// 40 百分位数值为 9.8// 第 50 个百分位数值为 11.16// 60 百分位数值为 12.8// 70 百分位数值为 14.8// 80 百分位数值为 18.3// 90 百分位数值为 25.8// 100个百分位值为3950611.6//

如您所见,100 是一个不错的票价,但被认为是异常值,

所以我基本上转向了可视化,

我整理了我的票价值并绘制了它

正如你最后看到的那样,几乎没有偏斜

所以基本上放大了,

像这样,

然后我将它放大到第 50 个到倒数第二个百分位数

瞧,我得到了我的阈值,即 1000,

这种方法在实际术语中称为“肘法”,您正在做的是第一步,如果您不满意,这可以作为找到那些阈值的第二步,

我建议您从一列到另一列并使用这些技术中的任何一种,因为如果您从一列到另一列,您就会知道您丢失了多少数据,因为丢失数据就是丢失了信息。

我个人比较关注可视化,最终还是要看数据。

all_columns = [df.columns] #This will give you list of all column names
all_columns = all_columns.remove('G_DIFF') # This will remove the column name that doesn't include those 12 columns

for column in all_columns:
    roll = df[column].rolling(24,center = True) #24h window
    mean, std = roll.mean(), roll.std()
    cut = std*3
    low, up = mean - cut, mean+cut
    tr.loc[(df[column] < low) | (df[column] > up) | (df[column].isna()), "outliers"] = df[column]
    tr.loc[(df[column] >= low) & (df[column] <= up), column] = df[column]
    tr.loc[tr[column].isna(),column] = tr[column].bfill() #to input a value when a datum is NaN