突出显示 matplotlib 图形的 pandas 数据框中的异常值

Highlight outliers in pandas dataframe for matplotlib graph

我有 2 个使用 pandas 构建的数据框。当我的数据超出某个参数时,我可以使用布尔索引让 pandas 告诉我。 我想在与原始数据相同的图表上突出显示异常值。我的尝试已在下面的代码中被注释掉,其中 none 行得通。 我的问题是:如何突出显示图表中的异常值?

这是我的代码,用于在我的数据框中查找异常值:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn
#plt.style.use("dark_background")
plt.style.use("seaborn-bright")

x4 = (e[0].time[:47172])
y4 = (e[0].data.f[:47172])

x6 = (t[0].time[:47211])
y6 = (t[0].data.f[:47211])

df4 = pd.DataFrame({'Time': x4, 'Data': y4})
df4['Outlier'] = (df4['Data'] < 2) | (df4['Data'] > 4)
#----This prints out only outliers
df4[df4.Outlier] 

df6 = pd.DataFrame({'Time': x4, 'Data': y4})
df6['Outlier'] = (df6['Data'] < 2) | (df6['Data'] > 4)
#----This prints out only outliers
df6[df6.Outlier]

plt.xlabel('Relative Time in Seconds', fontsize=12)
plt.ylabel('Data', fontsize=12)
plt.grid(linestyle = 'dashed')

这只是绘制原始数据:

plt.plot(x4, y4)
plt.plot(x6, y6)
plt.show()

这是我的数据框的示例:

        Data          Time  Outlier
0      0.000      7.343689     True
1      0.000      7.391689     True
2      0.000      7.439689     True
...    ...       ...          ...
47169  2.315  15402.062500    False
47170  0.000  15402.110352     True
47171  0.000  18682.187500     True
[47172 rows x 3 columns]

这些是我的尝试无效:

#fig = plt.figure()
#ax=fig.add_subplot(111)
#ax.plot((df4 < 2), (df4 > 4), color="r")

^这个只是绘制了一条直线,这是不正确的。

#df4.plot((df4['Data'] < 2), (df4['Data'] > 4), color = "r")

^这个打印出的图表在 x 轴而不是时间上有 'True' 和 'False。

我在想类似这样的 for 循环可能会起作用,但我不确定如何实现它。任何 help/feedback 将不胜感激。

for True in 'Outlier':
    plt.plot(x4, y4, color='r')

您已经设法只打印异常值,所以现在您可以简单地将它们绘制在正常数据之上,例如:

plt.plot(x4, y4)  # Data
plt.plot(x4[df4.Outlier], y4[df4.Outlier], 'r.')  # Outlier highlights
plt.plot(x6, y6)
plt.plot(x6[df6.Outlier], y6[df6.Outlier], 'r.')
plt.show()

重要的是使用Boolean series(例如df4.Outlier)作为mask通过索引检索实际异常值 .在您的非功能性示例中,您正在绘制 mask 本身。


旁注 1: 您可以跳过代码中的整个 pandas 部分(除非您在其他地方需要),然后执行:

mask4 = np.logical_or(y4 < 2, y4 > 4)
mask6 = np.logical_or(y6 < 2, y6 > 4)

plt.plot(x4, y4)
plt.plot(x4[mask4], y4[mask4], 'r.')
plt.plot(x6, y6)
plt.plot(x6[mask6], y6[mask6], 'r.')

plt.show()

旁注 2: 您创建 df6 的行中存在错误:您使用的是 x4y4 x6y6 作为输入。


旁注 3:Boolean masking 相比,循环方法 少 effective/elegant,但这里是它是如何工作的(为了学习):

for index,truth_value in enumerate(df4.Outlier):
    if truth_value:
        plt.plot(x4[index], y4[index], 'r.')

或作为列表理解:

[plt.plot(x4[i], y4[i], 'r.') for i,t in enumerate(df4.Outlier) if t]