如何让Matplotlib标记所有异常值为不同颜色而非仅一个
解决散点图异常值标记问题
我帮你找出代码里的问题啦,你现在只显示一个异常值的核心原因是异常值筛选的逻辑错误,下面一步步给你分析和修正:
问题分析
你原来的异常值筛选代码outliers = normed[normed>2*std_dev]有两个关键问题:
- 这个判断是逐元素比较,会把所有大于2倍标准差的单个元素提取出来,变成一个一维数组,而不是保留完整的样本行结构
- 异常值的定义应该是“样本的某个特征与该特征的均值偏差超过2个标准差”,你没有考虑到绝对值(毕竟偏离可以是正向也可以是负向),而且没有筛选出完整的异常样本
修正后的完整代码
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 读取数据 data = pd.read_csv('1fXr31hcEemkYxLyQ1aU1g_50fc36ee697c4b158fe26ade3ec3bc24_Banknote-authentication-dataset- (1).csv') data = np.array(data) # 归一化处理 min_vals = np.min(data, 0) max_vals = np.max(data, 0) normed = (data - min_vals) / (max_vals - min_vals) # 计算归一化后数据的均值和标准差(按列计算) normed_mean = np.mean(normed, 0) normed_std = np.std(normed, 0) # 创建画布和绘图对象 fig, graph = plt.subplots() # 绘制基础散点图 graph.scatter(normed[:,0], normed[:,1], label='Normal Data') # 绘制均值点 graph.scatter(normed_mean[0], normed_mean[1], c='green', marker='*', s=100, label='Mean') # 筛选异常值:判断每个样本的第0列或第1列是否偏离均值超过2倍标准差 # 这里取绝对值,覆盖正向和负向的偏离 outlier_mask_0 = np.abs(normed[:,0] - normed_mean[0]) > 2 * normed_std[0] outlier_mask_1 = np.abs(normed[:,1] - normed_mean[1]) > 2 * normed_std[1] # 只要任意一个维度是异常,就标记为异常样本 outlier_mask = outlier_mask_0 | outlier_mask_1 outliers = normed[outlier_mask] # 绘制异常值点 graph.scatter(outliers[:,0], outliers[:,1], c='red', marker='x', s=80, label='Outliers') # 添加图例和标题,让图表更清晰 graph.legend() graph.set_xlabel('Feature 0 (Normalized)') graph.set_ylabel('Feature 1 (Normalized)') graph.set_title('Scatter Plot with Outliers Marked') plt.show()
关键修正点说明
- 变量名优化:把
min、max改成min_vals、max_vals,避免覆盖Python内置函数 - 异常值筛选逻辑:用掩码(mask)筛选出完整的异常样本行,而不是单个元素,同时加入绝对值判断负向偏离的情况
- 可视化优化:添加了图例、坐标轴标签和标题,让图表更易读,用不同的标记区分均值和异常值
这样修改后,所有符合你定义的异常值都会被标记成红色叉号啦~
内容的提问来源于stack exchange,提问作者user12264129
相关产品推荐
相关产品推荐

