如何根据每个区间的特定条件将数据标记为异常

How to mark data as anomalies based on specific condition in each interval

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

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

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 个时间实例)标记为红色?

不完全清楚您期望的输出。 然而,让我们考虑以下类似于您的数据集:

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为阈值的例子:

原回答


您可以轻松转换为 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')

设置

np.random.seed(1)
anom = pd.Series(np.random.choice([0, 1], p=[0.2, 0.8], size=10000))

print(anom)

0       1
1       1
2       0
3       1
4       0
       ..
9995    1
9996    1
9997    0
9998    0
9999    1
Length: 10000, dtype: int64

解决方案

检测异常

m = anom == 1
c = anom[m].groupby((~m).cumsum()).transform('count')
a = c[c > 25].clip(upper=1) # Detection threshold=25

绘制检测到的异常

fig, ax = plt.subplots(figsize=(12, 8))
bars = ax.bar(a.index, a, facecolor='red', edgecolor='red')

结果