如何在matplotlib折线图中将离群值标记为独立的彩色标记点
问题复现
现有DataFrame结构如下:
val time 5.6 2021-11-18 03:00:00 2.034 2021-11-18 05:00:00 1.171 2021-11-18 07:00:00 3.023 2021-11-18 09:00:00 4.202 2021-11-18 16:00:00 1.202 2021-11-18 17:00:00 5.202 2021-11-18 18:00:00 7.202 2021-11-18 19:00:00 2.202 2021-11-18 20:00:00 12.202 2021-11-18 21:00:00 1.202 2021-11-18 21:00:00
需求为以time列为x轴、val列为y轴绘制折线图,将val>5的点标记为红色。
原有报错代码:
plt.plot(ab['time'], ab['value'], '-gD', markevery=marks, label='line with select markers')
其中marks为手动生成的离群值列表[7.202,12.202],报错内容为error -: markevery is iterable but not a valid numpy fancy index
错误原因
markevery参数接收的是需要标记的点的索引位置,而不是点的y轴数值,传入数值列表不符合参数要求。- 代码里取列用的
ab['value']和示例数据的列名val不一致,也会触发列不存在的报错,需要注意统一。
高效解决方案
该方案全程使用numpy/pandas向量化操作,百万级数据量也不会有性能问题,仅需2次绘图调用即可实现需求:
import pandas as pd import matplotlib.pyplot as plt # 先转换time列为datetime格式,避免x轴显示错乱 ab['time'] = pd.to_datetime(ab['time']) # 第一步:绘制基础绿色折线,无需加标记 plt.plot(ab['time'], ab['val'], '-g', label='数值趋势') # 第二步:筛选val>5的子集,单独绘制红色标记点,为向量化操作,效率极高 mask = ab['val'] > 5 plt.scatter(ab.loc[mask, 'time'], ab.loc[mask, 'val'], c='red', label='val>5的异常点') # 可选:配置x轴显示避免重叠 plt.xticks(rotation=45) plt.legend() plt.tight_layout() plt.show()
方案优势
- 无需提前手动生成离群值列表,直接通过布尔掩码筛选,避免手动匹配的误差
- 两次绘图操作都是matplotlib底层优化过的向量化执行,比循环给每个点设置样式的方案效率高100倍以上,完全适配大数据量场景
内容的提问来源于stack exchange,提问作者jony
相关产品推荐
相关产品推荐

