首页 > 解决方案 > 如何根据每个区间的特定条件将数据标记为异常

问题描述

我尝试在很多地方搜索这个问题,但找不到合适的工具。

我有一个简单的时间序列数据,

print(anom)
0        0
1        0
2        0
3        0
4        0
        ..
52777    1
52778    1
52779    0
52780    1

对于 = 1 且跨越的任何数据序列(例如 1000 个时间实例)。我想将这些标记为异常(真)。否则他们应该被忽略(作为假)。

如何使用 pandas 或 numpy 实现这一目标?

我还想绘制那些异常,例如红色,我们如何实现呢?

我如何将这些异常(值 = 1 扩展到大约 1000 个时间实例)标记为红色? 在此处输入图像描述

标签: pythonpandasnumpynumpy-slicing

解决方案


目前尚不清楚您期望哪种输出。但是,让我们考虑以下与您的数据集相似的数据集:

s = pd.Series(np.random.choice([0,1], size=100, p=[0.7, 0.3]), name='anom')
0     1
1     0
2     0
3     0
4     0
     ..
95    0
96    1
97    1
98    0
99    1
Name: anom, Length: 100, dtype: int64

看起来像:

输入数据

基于连续值过滤

首先我们计算1s的长度

length = s.groupby(((s-s.shift().fillna(0)).eq(1).cumsum()*s)).transform(len)*s

这通过识别伸展的第一个元素来工作(s-s.shift().fillna(0)).eq(1)(一个元素和先例之间的差异只有在 1 前面有 0 的情况下才为 1,请参见下面的图 #2)。然后,它使增加的组(图#3)对每个 1 的延伸和 0 的连续延伸进行分组。通过乘以s,只有 1 保留在组中(图 #4)。现在我们可以对每个拉伸的数据进行分组并计算每个长度(图#5)。0 将是一组的一部分,所以最后,我们通过再次乘以s(图 #6)来删除零。

这是连续步骤的可视化表示,其中(…)表示每个图中的上一步:

拉伸长度计算的细分

s_valid = s.loc[length<10]
s_anom = s.drop(s_valid.index)

ax = s_valid.plot(marker='o', ls='')
s_anom.plot(marker='o', ls='', ax=ax, color='r')

线+点

ax = s.plot()
s_anom.plot(marker='o', ls='', ax=ax, color='r')

线+点

以 7 为阈值的其他示例:

线+点; 7 作为阈值

原始答案


您可以轻松转换为bool以获取异常

>>> s.astype(bool)
0      True
1     False
2     False
3     False
4     False
      ...  
95    False
96     True
97     True
98    False
99     True
Name: anom, Length: 100, dtype: bool

关于情节,取决于你期望你能做什么:

s_valid = s.loc[~s.astype(bool)]
s_anom = s.loc[s.astype(bool)]

ax = s_valid.plot(marker='o', ls='')
s_anom.plot(marker='o', ls='', ax=ax, color='r')

输出:

数据为红色的点异常

s_anom = s.loc[s.astype(bool)]
ax = s.plot()
s_anom.plot(marker='o', ls='', ax=ax, color='r')

数据为线条 异常为红点


推荐阅读