【数学建模学习笔记】异常值处理
零基础入门:用 Pandas 处理异常值
如果你是刚接触数据分析的 “小白”,不用怕!这篇文章会用最简单的语言,带你搞懂 “异常值处理” 是什么、为什么要做,以及怎么用 Pandas(Python 里最常用的数据分析工具)完成 3 种主流的异常值处理方法。
一、先搞懂基础概念:什么是异常值?为什么要处理它?
1. 异常值 =“不合群的数据”
比如你们班同学的身高大多在 150-180cm 之间,但有一个数据写的是 “250cm”—— 这个 “250cm” 就是异常值。
它可能是录入错误(比如多写了个 “2”)、测量失误(仪器坏了),也可能是真的特殊情况,但不管哪种,都会干扰后续分析(比如算平均身高时,这个值会让结果严重偏高)。
2. 为什么必须处理异常值?
举个例子:如果用包含异常值的 “用户消费数据” 做分析,可能会误以为有用户一次花了 10 万元(实际是多写了一个 0),进而做出错误的商业决策(比如专门推高价产品给这类 “假高消费用户”)。
所以,处理异常值是数据分析的 “前置步骤”,就像做饭前要把坏菜挑出去一样。
二、准备工作:先把工具和数据备好
在开始处理前,我们需要先 “搭好环境”—— 就像做饭前要准备好锅碗瓢盆一样。
1. 需要的 “工具”(Python 库)
- Pandas:处理表格数据的核心工具(比如读数据、改数据)
- NumPy:帮我们做数学计算(比如算中位数、标准差)
2. 数据长什么样?
我们用的是一个包含 10 个变量(x1 到 x10)的表格数据,每一行是一个样本,每一列是一个指标。比如前 5 行长这样:
x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 |
---|---|---|---|---|---|---|---|---|---|
85.28 | 85.74 | 87.88 | 70.19 | 97.13 | 84.09 | 89.67 | 90.71 | 88.07 | 68.15 |
74.30 | 74.41 | 71.50 | 140.00 | 74.95 | 81.70 | 61.27 | 74.73 | 72.19 | 88.11 |
85.22 | 86.23 | 83.88 | 87.48 | 73.42 | 73.19 | 88.53 | 86.98 | 83.25 | 90.07 |
能看到有些数据明显 “不对劲”,比如第二行的 x4 是 140.00,其他 x4 数据大多在 70-90 之间 —— 这就是我们要找的异常值。
3. 怎么加载数据?
复制下面的代码到 Python 里(比如 Jupyter Notebook),就能加载数据并查看前 5 行:
# 导入需要的工具库
import numpy as np
import pandas as pd# 加载数据(直接从网上读取,不用自己下载)
df = pd.read_excel('https://labfile.oss.aliyuncs.com/courses/40611/%E5%BC%82%E5%B8%B8%E5%80%BC%E5%A4%84%E7%90%86.xlsx')# 查看数据前5行,了解数据样式
df.head()
三、3 种异常值处理方法:从原理到代码(小白也能懂)
接下来是重点!我们会讲 3 种最常用的异常值处理方法:MAD 方法、IQR 方法、3 Sigma 方法。每种方法都会先讲 “怎么判断异常值”,再讲 “怎么用代码实现”,最后用 “中位数替换异常值”(最常用的处理方式)。
方法 1:中位数绝对偏差(MAD)法 —— 对 “极端值” 超宽容
1. 原理:用 “中位数” 找异常
MAD 方法的核心是 “中位数”—— 它不像 “平均数” 那样容易被极端值影响(比如 10 个人工资大多 5k,1 个人 100k,平均数会变高,但中位数不变)。
步骤很简单:
- 算每列数据的中位数(比如 x1 列的中位数是 80,意思是一半数据比 80 大,一半比 80 小);
- 算每个数据到中位数的 “绝对距离”(比如 x1 里有个数据是 90,距离就是 | 90-80|=10);
- 算这些 “绝对距离” 的中位数,就是MAD;
- 设定一个阈值(通常是 3):如果某个数据到中位数的距离 > 3×MAD,就判定为异常值。
2. 代码实现(复制就能用)
# 第一步:定义一个函数,计算MAD(中位数绝对偏差)
def mad(arr):median = np.median(arr) # 算数据的中位数return np.median(np.abs(arr - median)) # 算“数据-中位数”的绝对距离的中位数(即MAD)# 第二步:算每列的中位数和MAD
medians = df.median() # 每列的中位数(比如x1的中位数、x2的中位数...)
mads = df.apply(mad) # 每列的MAD(用上面定义的mad函数算)# 第三步:识别异常值(距离>3×MAD就是异常)
outliers_mad = (np.abs(df - medians) / mads) > 3# 第四步:处理异常值(用该列的中位数替换异常值)
df_mad = df.mask(outliers_mad, medians, axis=1)# 查看处理后的数据前5行
df_mad.head()
3. 适合用在什么场景?
- 数据量比较小(比如只有几十行);
- 数据里有明显的 “极端值”(比如突然出现一个超大 / 超小的数);
- 不想让极端值影响判断(比如算贫困线时,不能被富豪的收入干扰)。
方法 2:四分位距(IQR)法 —— 偏态数据的 “救星”
1. 原理:用 “四分位数” 划分正常范围
“四分位” 就是把数据从小到大分成 4 份,比如:
- Q1(下四分位):25% 的数据比它小,75% 的数据比它大;
- Q3(上四分位):75% 的数据比它小,25% 的数据比它大;
- IQR(四分位距)= Q3 - Q1(中间 50% 数据的范围)。
判断异常值的规则:
- 小于「Q1 - 1.5×IQR」的是异常值;
- 大于「Q3 + 1.5×IQR」的是异常值。
比如:x3 列的 Q1=77,Q3=88,IQR=11,那么正常范围是 77-1.5×11=60.5 到 88+1.5×11=104.5,超出这个范围的就是异常值。
2. 代码实现(复制就能用)
# 第一步:算每列的Q1(25%分位数)、Q3(75%分位数)、IQR
Q1 = df.quantile(0.25) # 25%分位数
Q3 = df.quantile(0.75) # 75%分位数
IQR = Q3 - Q1 # 四分位距# 第二步:识别异常值(超出Q1-1.5×IQR或Q3+1.5×IQR)
outliers_iqr = (df < (Q1 - 1.5 * IQR)) | (df > (Q3 + 1.5 * IQR))# 第三步:处理异常值(用该列的中位数替换异常值)
df_iqr = df.mask(outliers_iqr, medians, axis=1)# 查看处理后的数据前5行
df_iqr.head()
3. 适合用在什么场景?
- 数据是 “偏态分布” 的(比如收入数据:大部分人收入低,少数人收入极高,数据往一边偏);
- 不想被极端值影响(因为 IQR 只看中间 50% 的数据,极端值根本不参与计算);
- 常见于金融、医疗数据(比如患者的血压、客户的消费金额,大多是偏态的)。
方法 3:3 Sigma 法 —— 正态分布数据的 “专属工具”
1. 原理:用 “均值 + 标准差” 圈定正常范围
“Sigma(σ)” 就是标准差,用来表示数据的 “分散程度”(比如全班成绩的标准差小,说明大家分数差不多;标准差大,说明分数差距大)。
这种方法有个前提:数据要符合 “正态分布”(比如身高、体重、考试分数,大多符合 “中间多、两边少” 的钟形分布)。
判断异常值的规则:
- 正常范围是「均值 ± 3× 标准差」;
- 超出这个范围的,大概率是异常值(因为正态分布中,只有 0.27% 的数据会落在这个范围外,相当于 1000 个数据里只有 3 个可能是正常的)。
比如:x4 列的均值 = 85,标准差 = 10,那么正常范围是 85-3×10=55 到 85+3×10=115,超出的就是异常值。
2. 代码实现(复制就能用)
# 第一步:算每列的均值和标准差
means = df.mean() # 每列的均值
std_devs = df.std() # 每列的标准差# 第二步:识别异常值(超出均值±3×标准差)
outliers_3sigma = (np.abs(df - means) > 3 * std_devs)# 第三步:处理异常值(用该列的中位数替换异常值)
df_3sigma = df.mask(outliers_3sigma, medians, axis=1)# 查看处理后的数据前5行
df_3sigma.head()
3. 适合用在什么场景?
- 数据符合 “正态分布”(比如自然科学实验数据、大样本的用户行为数据);
- 数据量比较大(比如几千、几万行);
- 需要用 “概率” 来判断异常(比如质量检测:产品尺寸超出 3σ 范围,就判定为不合格)。
四、3 种方法怎么选?一张表讲清楚
很多小白会纠结 “该用哪种方法”,其实核心是看你的数据特点,用下面这张表对照选就行:
方法 | 核心优点 | 适用场景 | 不适用场景 |
---|---|---|---|
MAD 法 | 对极端值不敏感,稳健 | 小数据集、有明显极端值的数据 | 数据量大、需要用概率判断的场景 |
IQR 法 | 适合偏态分布,不受极端值影响 | 偏态数据(如收入、消费)、金融 / 医疗数据 | 数据符合正态分布、需要精确概率的场景 |
3 Sigma 法 | 基于概率,适合正态分布 | 正态分布数据、大数据集、质量检测等场景 | 偏态数据、小数据集(容易误判) |
五、小白必看:常见问题解答
1. 处理异常值只能 “用中位数替换” 吗?
不是!除了中位数替换,还有两种常用方式:
- 删除异常值:如果异常值很少(比如 1000 行里只有 1-2 个),且确定是错误数据(比如录入错误),可以直接删掉;
- 用均值替换:如果数据符合正态分布,且异常值不多,也可以用该列的均值替换(但不如中位数稳健)。
2. 怎么判断数据是不是正态分布?
小白可以用 “可视化” 快速判断:
# 画直方图(看数据是不是“钟形”)
import matplotlib.pyplot as plt
df['x1'].hist() # 看x1列的分布,其他列改列名就行
plt.show()
如果直方图长得像 “两边低、中间高” 的钟形,就大概率是正态分布。
3. 所有数据都需要处理异常值吗?
不一定!如果你的分析目标就是 “找异常”(比如欺诈检测:找异常的交易记录),那不仅不能处理,还要重点分析异常值。只有当异常值会干扰你的分析目标时,才需要处理。
六、总结
异常值处理是数据分析的 “入门必修课”,记住 3 个核心点:
- 异常值是 “不合群的数据”,会干扰分析结果,需要处理;
- 3 种方法各有侧重:MAD 稳、IQR 偏、3 Sigma 正态;
- 选方法看数据特点,不用死记硬背,多练几次就会了。