京公网安备 11010802034615号
经营许可证编号:京B2-20210330
作者 | 刘顺祥
来源 | 数据分析1480
在《Python数据清洗(一):类型转换和冗余数据删除》和《Python数据清洗(二):缺失值识别与处理》文中已经讲解了有关数据中重复观测和缺失值的识别与处理,在本节中将分享异常值的判断和处理方法。
异常值也称为离群点,就是那些远离绝大多数样本点的特殊群体,通常这样的数据点在数据集中都表现出不合理的特性。如果忽视这些异常值,在某些建模场景下就会导致结论的错误(如线性回归模型、K均值聚类等),所以在数据的探索过程中,有必要识别出这些异常值并处理好它们。
异常值的识别
通常,异常值的识别可以借助于图形法(如箱线图、正态分布图)和建模法(如线性回归、聚类算法、K近邻算法),在本期内容中,将分享两种图形法,在下一期将分享基于模型识别异常值的方法。
箱线图法
箱线图技术实际上就是利用数据的分位数识别其中的异常点,该图形属于典型的统计图形,在学术界和工业界都得到广泛的应用。箱线图的形状特征如下图所示:
图中的下四分位数指的是数据的25%分位点所对应的值(Q1);中位数即为数据的50%分位点所对应的值(Q2);上四分位数则为数据的75%分位点所对应的值(Q3);上须的计算公式为Q3+1.5(Q3-Q1);下须的计算公式为Q1-1.5(Q3-Q1)。其中,Q3-Q1表示四分位差。如果采用箱线图识别异常值,其判断标准是,当变量的数据值大于箱线图的上须或者小于箱线图的下须时,就可以认为这样的数据点为异常点。
所以,基于上方的箱线图,可以定义某个数值型变量中的异常点和极端异常点,它们的判断表达式如下表所示:
在Python中可以使用matplotlib模块实现数据的可视化,其中boxplot函数就是用于绘制箱线图的。下面以1700年至1988年太阳黑子数量的数据为例,利用箱线图法识别数据中的异常点和极端异常点。具体的代码如下:
# 导入第三方模块 import pandas as pd import matplotlib.pyplot as plt # 导入数据 sunspots = pd.read_csv(r'C:\Users\Administrator\Desktop\sunspots.csv') # 绘制箱线图(1.5倍的四分位差,如需绘制3倍的四分位差,只需调整whis参数) plt.boxplot(x = sunspots.counts, # 指定绘制箱线图的数据 whis = 1.5, # 指定1.5倍的四分位差 widths = 0.7, # 指定箱线图的宽度为0.8 patch_artist = True, # 指定需要填充箱体颜色 showmeans = True, # 指定需要显示均值 boxprops = {'facecolor':'steelblue'}, # 指定箱体的填充色为铁蓝色 # 指定异常点的填充色、边框色和大小 flierprops = {'markerfacecolor':'red', 'markeredgecolor':'red', 'markersize':4}, # 指定均值点的标记符号(菱形)、填充色和大小 meanprops = {'marker':'D','markerfacecolor':'black', 'markersize':4}, medianprops = {'linestyle':'--','color':'orange'}, # 指定中位数的标记符号(虚线)和颜色 labels = [''] # 去除箱线图的x轴刻度值 ) # 显示图形 plt.show()
如上图所示,利用matplotlib子模块pyplot中的boxplot函数可以非常方便地绘制箱线图,其中左图的上下须设定为1.5倍的四分位差,右图的上下须设定为3倍的四分位差。从左图可知,发现数据集中至少存在5个异常点,它们均在上须之上;而在右图中并没有显示极端异常点。
通过上图可以直观地发现数据中是否存在异常点或极端异常点,但无法得知哪些观测为异常点,以及这些异常点的具体数值。为解决该问题,读者可以通过下方的代码实现查询:
# 计算下四分位数和上四分位 Q1 = sunspots.counts.quantile(q = 0.25) Q3 = sunspots.counts.quantile(q = 0.75) # 基于1.5倍的四分位差计算上下须对应的值 low_whisker = Q1 - 1.5*(Q3 - Q1) up_whisker = Q3 + 1.5*(Q3 - Q1) # 寻找异常点 sunspots.counts[(sunspots.counts > up_whisker) | (sunspots.counts < low_whisker)]
正态分布图法
根据正态分布的定义可知,数据点落在偏离均值正负1倍标准差(即sigma值)内的概率为68.2%;数据点落在偏离均值正负2倍标准差内的概率为95.4%;数据点落在偏离均值正负3倍标准差内的概率为99.6%。
所以,换个角度思考上文提到的概率值,如果数据点落在偏离均值正负2倍标准差之外的概率就不足5%,它属于小概率事件,即认为这样的数据点为异常点。同理,如果数据点落在偏离均值正负3倍标准差之外的概率将会更小,可以认为这些数据点为极端异常点。为使读者直观地理解文中提到的概率值,可以查看标准正态分布的概率密度图,如下图所示:
进一步,基于上图的结论,可以按照下表中的判断条件,识别出数值型变量的异常点和极端异常点,如下表所示:
利用正态分布的知识点,结合pyplot子模块中的plot函数绘制折线图和散点图,并借助于两条水平参考线识别异常值或极端异常值。
接下来以某公司的支付转化率数据为例,使用正态分布的特性识别数据集中的异常点和极端异常点,该数据呈现的是2017年第三季度每天的支付转化率。我们利用如上介绍的plot函数,识别数据中可能存在的异常点或极端异常点。具体代码如下:
# 读入外部数据 pay_ratio = pd.read_excel(r'C:\Users\Administrator\Desktop\pay_ratio.xlsx') # 绘制单条折线图,并在折线图的基础上添加点图 plt.plot(pay_ratio.date, # x轴数据 pay_ratio.ratio, # y轴数据 linestyle = '-', # 设置折线类型 linewidth = 2, # 设置线条宽度 color = 'steelblue', # 设置折线颜色 marker = 'o', # 往折线图中添加圆点 markersize = 4, # 设置点的大小 markeredgecolor='black', # 设置点的边框色 markerfacecolor='black') # 设置点的填充色 # 显示图形 plt.show() # 添加上下界的水平参考线(便于判断异常点,如下判断极端异常点,只需将2改为3) plt.axhline(y = pay_ratio.ratio.mean() - 2* pay_ratio.ratio.std(), linestyle = '--', color = 'gray') plt.axhline(y = pay_ratio.ratio.mean() + 2* pay_ratio.ratio.std(), linestyle = '--', color = 'gray') # 导入模块,用于日期刻度的修改(因为默认格式下的日期刻度标签并不是很友好) import matplotlib as mpl # 获取图的坐标信息 ax = plt.gca() # 设置日期的显示格式 date_format = mpl.dates.DateFormatter("%m-%d") ax.xaxis.set_major_formatter(date_format) # 设置x轴每个刻度的间隔天数 xlocator = mpl.ticker.MultipleLocator(7) ax.xaxis.set_major_locator(xlocator) # 为了避免x轴刻度标签的紧凑,将刻度标签旋转45度 plt.xticks(rotation=45)
如上图所示,左图中的两条水平线是偏离均值正负2倍标准差的参考线,目测有6个样本点落在参考线之外,可以判定它们属于异常点;而对于右图中偏离均值正负3倍标准差的参考线来说,仅有1个样本点落在参考线之外,即说明该样本点就是2017年第三季度的唯一极端异常点。
同理,也可以借助于下面的代码,查询出异常点所对应的水流量:
# 计算判断异常点和极端异常点的临界值 outlier_ll = pay_ratio.ratio.mean() - 2* pay_ratio.ratio.std() outlier_ul = pay_ratio.ratio.mean() + 2* pay_ratio.ratio.std() extreme_outlier_ll = pay_ratio.ratio.mean() - 3* pay_ratio.ratio.std() extreme_outlier_ul = pay_ratio.ratio.mean() + 3* pay_ratio.ratio.std() # 寻找异常点 pay_ratio.loc[(pay_ratio.ratio > outlier_ul) | (pay_ratio.ratio < outlier_ll), ['date','ratio']] # 寻找极端异常点 pay_ratio.loc[(pay_ratio.ratio > extreme_outlier_ul) | (pay_ratio.ratio < extreme_outlier_ll), ['date','ratio']]
异常点
极端异常点
尽管基于箱线图的分位数法和基于正态分布的参考线法都可以实现异常值和极端异常值的识别,但是在实际应用中,需要有针对性的选择。如果待判断的变量近似服从正态分布,建议选择正态分布的参考线法识别异常点,否则使用分位数法识别异常点。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
一、问题:为什么 ID 会"断号" 很多刚接触 MySQL 的同学都会有一个困惑:表里的主键 ID 是自增的,删了中间几行数据之后,ID 变 ...
2026-10-22一、问题场景:为什么会重复 JOIN 同一个子查询 在写复杂 SQL 时,经常遇到这种需求:同一张表或同一个聚合子查询,要和主表关联 ...
2026-10-22人力资源专员是HR体系的执行入口。招聘信息发布、简历初筛、面试安排、考勤汇总、入离职手续、劳动合同与档案管理,大多由这个岗 ...
2026-10-22人力资源经理问“必学技巧”,真正要解决的不是知识清单不够长,而是时间有限、业务催得紧,学完却用不上。更有效的路径是:先用 ...
2026-10-22内容营销岗位的核心任务,不是“把文案写得更漂亮”,而是围绕目标受众,用持续的内容供给影响认知、推动转化并沉淀复购。它至少 ...
2026-10-22理财经理培训课程很多,难的是判断“先学什么、后学什么、学完能做什么”。与其按课程名称罗列,不如先看岗位任务:客户分层与维 ...
2026-10-22理财经理的知识结构,可以先用一句话概括:合规与产品知识决定“不出错”,客户经营与资产配置决定“够不够专业”,市场研判与数 ...
2026-10-22经济学背景做数据分析,优势不在工具,而在问题意识:供需如何相互作用、成本与收益如何权衡、变量之间是相关还是因果。真正的缺 ...
2026-10-22需要,但要把“需要”理解准确。经济学本身就在处理数据:GDP、物价、就业、企业营收、问卷调研,都是经济分析的原料。真正的区 ...
2026-10-22经济学分析能力不是单一技能,它至少由三层构成:把现实问题转成可检验假设的理论框架能力、用数据与统计方法验证假设的工具能力 ...
2026-10-22金融分析师的知识提升,先补的不是更多模型,而是让结论可复核的底层能力。按任务顺序,大致是四层:财务与业务理解、指标口径管 ...
2026-10-22金融分析师的“通用技能”,指换到不同机构、不同行业组仍用得上的底层能力,而非某家公司内部系统的操作经验。按任务拆,日常要 ...
2026-10-22先给结论:数据分析证书不是金融分析师的准入条件,招聘方也不会因为一张证书就直接判断你能做分析。要不要考,取决于你当前任务 ...
2026-10-22金融分析师的核心技能,不是“会看K线”或“会讲宏观”,而是能把一家公司、一个行业或一类资产,转化为可核查的数据判断与书面 ...
2026-10-22产品经理的知识提升,不是把需求文档、原型、SQL、数据分析、项目管理都学一遍,而是先对准目标岗位的真实任务,找出自己最缺的 ...
2026-10-22产品专员提升工作知识,最有效的方式不是先囤课程,而是围绕日常交付的四件事来补:需求调研与优先级判断、原型与PRD表达、竞品 ...
2026-10-22产品运营专员提升个人能力,常见误区是先把Excel、SQL、Python列成一张学习清单,然后从第一个工具开始学。更有效的做法是先回答 ...
2026-10-22产品运营的能力提升,最怕从“课程目录”出发:今天学增长模型,明天背SQL语法,学完却说不清自己负责的功能为什么激活率低。更 ...
2026-10-22产品经理的技能和影响力不是两条分开的赛道。技能决定你能不能把问题分析清楚、把方案设计对;影响力决定你的判断能否被团队接受 ...
2026-10-22产品经理要学的数据分析能力,不是“会写SQL”或“会用BI工具”这么简单。更准确地说,是围绕需求评估、功能迭代、指标监控、实 ...
2026-10-22