统计数据异常值的处理——R和Python语言

在统计数据分析中,异常值指的是在数据集中显得特别偏离或不符合整体趋势的观测值。它们可能由于种种原因与大多数数据点存在明显差异,如测量误差、录入错误、极端事件或特殊情况等。异常值的存在可以对数据分析的结果产生显著影响,有时会扭曲平均值、增加方差,甚至改变分析结论。因此,识别和处理异常值是数据分析中的重要环节。尽管异常值可能代表的是某种数据错误,但有时它们也具有特殊意义。例如,在科学实验或经济研究中,异常值可能反映了重要的突变、突发事件,或者揭示了有价值的潜在信息。因此,在数据处理中,异常值的识别和理解要结合具体背景与领域知识进行判断。面对收集而来的数据,异常值(outlier)是数据清洗的重要环节,异常值可能直接会导致后面的数据分析、建模工作出现偏差,下面就给大家介绍一下如何处理数据中的异常值。

一、异常值概述

在统计数据分析中,异常值(Outliers)是指远离其他数据点,显得异常、偏离整体趋势的观测值。通常,异常值与数据集中大部分数据存在显著差异,可能由于错误的记录、实验条件的变化、极端情况的发生,或是某些特殊原因引起。它们可能会对统计分析的结果产生显著影响,因此识别、理解和处理异常值是统计数据分析中的重要环节。在不同的数据场景中,鉴别异常值有不同的标准,常规有以下几种:

(1)数字超过某个标准值
这是最常用的异常值判断方法之一。主要是看数据中的最大值或最小值,依据专业知识或个人经验,判断是否超过了理论范围值,数据中有没有明显不符合实际情况的错误。比如,测量成年男性身高(M),出现17.8m这样的数据,显然不符合实际情况。又或者,如问卷数据使用1-5级量表进行研究,出现-2,-3这类数据,则可能提示为跳转题、空选等。
(2)数据大于±3标准差
3σ 原则是在数据服从正态分布的时候用的比较多,在这种情况下,异常值被定义为一组测定值中与平均值的偏差超过3倍标准差的值。在数据处理的时候,按照正态分布的性质,三个标准差以外的数据都可以被看作是错误的数据从而排除掉。

异常值的定义并不总是绝对的。在许多情况下,异常值是根据上下文、分析目标以及数据的分布形态来确定的。例如,在高度集中的正态分布数据中,位于均值两侧3倍标准差之外的点通常被认为是异常值;而在某些不规则分布或带有长尾特征的数据中,某些数据点虽然偏离较远,但可能仍属于该分布的合理范围。因此,异常值的识别不仅要依赖数据本身,还需要结合具体问题进行判断。异常点在某些场景下极为重要,如疾病预测,通常健康人的身体指标在某些维度上是相似,如果一个人的身体指标出现了异常,那么他的身体情况在某些方面肯定发生了改变,当然这种改变并不一定是由疾病引起(通常被称为噪音点),但异常的发生和检测是疾病预测一个重要起始点。相似的场景也可以应用到信用欺诈,网络攻击等等。

1.1 异常值的分类

异常值可以根据其来源或性质划分为以下几类:

测量错误或记录错误的异常值:这是最常见的异常值类型,通常是由于仪器故障、实验条件不当或数据输入错误等原因造成的。例如,在某次温度记录中,某一条数据显示为500度,而实际可能是5度,这就是典型的记录错误。
自然异常值:这种异常值是真实存在的,并非由于误差或错误造成。例如,在人口统计数据中,极个别超高收入者或非常高龄的人群可能是真实的极端值,这类异常值并不应该被轻易忽略或删除。
模型不适合的异常值:在某些情况下,异常值的出现可能是因为所使用的统计模型不适合数据。举个例子,如果我们假设某一变量服从正态分布,但实际上它可能具有偏斜分布,这时“异常值”实际上是由于模型不当造成的。

1.2 异常值的检测方法

为了有效处理异常值,首先需要识别和检测它们。以下是常见的异常值检测方法:

箱线图法:箱线图是一种通过数据的四分位数展示数据分布情况的可视化工具。通过计算上四分位数(Q3)和下四分位数(Q1),箱线图可以帮助识别异常值。通常认为,任何超出上下四分位距(IQR,Q3 - Q1)的1.5倍以上的点为异常值;如果超过3倍,则可以认为是极端异常值。
Z值检验(Z-Score):Z值检验是基于正态分布的一种标准化方法。通过计算每个数据点与均值的差距,并将该差距标准化为标准差单位,Z值可以帮助判断数据点与其他数据的偏离程度。一般认为,绝对值超过3的Z值代表该数据可能是异常值。
MAD法(Median Absolute Deviation):MAD是以中位数为基准,计算数据偏离中位数的绝对偏差。与Z值检验不同的是,MAD对于非正态分布的数据更为稳健,特别是在处理具有长尾特征或不对称分布的数据时。通过计算MAD,可以更稳健地判断哪些数据偏离大部分数据。
基于回归模型的残差分析:在回归模型中,残差是实际值与预测值之间的差异。通过分析残差的分布情况,可以检测是否存在数据点严重偏离预测值,这些偏离较大的点通常被认为是异常值。
距离法(如马氏距离):对于多维数据,马氏距离是一种常用的异常值检测方法。它通过计算每个数据点到数据中心的距离,并将距离标准化,以判断数据点与其他点的偏离程度。特别是在处理高维数据时,马氏距离能够有效检测异常点。

1.3 异常值的处理方法

检测到异常值后,处理方式因具体情况而异。常见的处理方法包括以下几种:

删除异常值:这是最直接的处理方法,尤其适用于明显由测量错误或录入错误导致的异常值。例如,在某个温度记录中,500度的值明显是不合理的,删除这个异常值可以避免对整体分析的干扰。然而,需要谨慎使用该方法,特别是在异常值可能具有潜在意义时,如极端天气数据等。
用合理的替代值代替:对于一些可以判断为错误的异常值,替换为合理的值是一种替代删除的方式。例如,可以用样本的均值或中位数替代异常值。对于时间序列数据,也可以通过插值方法来替换异常值,如使用邻近数据的趋势线来预测异常值的合理替代。
数据变换:通过对数据进行适当的变换(如对数变换、平方根变换等),可以减少异常值的影响。在某些情况下,变换后的数据能够更加符合正态分布,并使得异常值的影响不再显著。这种方法在处理具有长尾分布的数据时特别有用。
分组分析:对于一些含有多个子群的复杂数据,可能整体看似存在异常值,但在不同子群中表现正常。这时,可以将数据按类别或特征分组,再进行单独分析。通过分组分析,能够更好地理解异常值的来源,并采取适当的处理方法。
使用鲁棒统计方法:鲁棒统计方法是在存在异常值的情况下,仍能提供稳定结果的一类统计方法。与传统统计方法相比,鲁棒方法对异常值不敏感,常见的鲁棒统计方法包括中位数、MAD(中位数绝对偏差)等。这类方法特别适合在异常值无法直接处理或无法确定其是否有意义时使用。
建立模型并加入异常值作为研究对象:在某些情况下,异常值本身可能蕴含着重要的信息,而非简单的错误。例如,在金融数据中,某些异常的交易行为可能反映了市场的极端波动,忽略这些异常值可能会丢失有价值的信息。因此,建立包含异常值的模型,并专门研究异常值的形成机制和其对系统的影响,有时能够带来新的洞见。

二、异常值箱线图的鉴别

箱线图(Box plot)也称箱须图(Box-whisker Plot)、箱线图、盒图,可以用来反映一组或多组连续型定量数据分布的中心位置和散布范围,因形状如箱子而得名。1977年,美国著名数学家John W. Tukey首先在他的著作《Exploratory Data Analysis》中介绍了箱形图。用于反映一组或多组连续型定量数据分布的中心位置和散布范围。箱形图包含数学统计量,不仅能够分析不同类别数据各层次水平差异,还能揭示数据间离散程度、异常值、分布差异等等。

2.1 箱线图

箱线图很适合鉴别异常值,具体的判断标准是计算出数据中的最小估计值和最大估计值。如果数据数据超过这一范围,说明该值可能为异常值。箱盒图会自动标出此范围,异常值则用圆圈表示。连续型数据:在一定区间内可以任意取值的变量叫连续变量,其数值是连续不断的。例如,生产零件的规格尺寸,人体测量的身高、体重等,其数值只能用测量或计量的方法取得。可视化这类数据的图表主要有箱形图和直方图。离散型数据:数值只能用自然数或整数单位计算的则为离散变量。例如,企业个数,职工人数,设备台数等,只能按计量单位数计数,数值一般用计数方法取得。大多数图表可视化的都是这类数据,比如柱状图、折线图等。
在箱线图中,箱子的中间有一条线,代表了数据的中位数。箱子的上下底,分别是数据的上四分位数(Q3)和下四分位数(Q1),这意味着箱体包含了50%的数据。因此,箱子的高度在一定程度上反映了数据的波动程度。上下边缘则代表了该组数据的最大值和最小值。有时候箱子外部会有一些点,可以理解为数据中的“异常值”。由于箱线图不像柱状图、折线图那样简单常见,许多人都对它敬而远之。但只要我们搞清楚了以下几个统计学的基本概念,箱线图也可以变得“平易近人”。
四分位数是一组数据按照从小到大顺序排列后,把该组数据四等分的数,称为四分位数。第一四分位数 (Q1)、第二四分位数 (Q2,也叫“中位数”)和第三四分位数 (Q3)分别等于该样本中所有数值由小到大排列后第25%、第50%和第75%的数字。第三四分位数与第一四分位数的差距又称四分位距(interquartile range, IQR),包含全部数据的一半。

2.2 异常值的鉴别

箱线图可以直观明了地识别数据批中的异常值。箱形图可以用来观察数据整体的分布情况,利用中位数,25/%分位数,75/%分位数,上边界,下边界等统计量来来描述数据的整体分布情况。通过计算这些统计量,生成一个箱体图,箱体包含了大部分的正常数据,而在箱体上边界和下边界之外的,就是异常数据。判断数据的偏态和尾重。对于标准正态分布的大样本,中位数位于上下四分位数的中央,箱形图的方盒关于中位线对称。中位数越偏离上下四分位数的中心位置,分布偏态性越强。异常值集中在较大值一侧,则分布呈现右偏态;异常值集中在较小值一侧,则分布呈现左偏态。比较多批数据的形状。箱子的上下限,分别是数据的上四分位数和下四分位数。这意味着箱子包含了50%的数据。因此,箱子的宽度在一定程度上反映了数据的波动程度。箱体越扁说明数据越集中,端线(也就是“须”)越短也说明数据集中。凭借着这些“独门绝技”,箱线图在使用场景上也很不一般,最常见的是用于质量管理、人事测评、探索性数据分析等统计分析活动。
在箱线图中,异常值(也称为离群点)是那些远离大多数数据的点。标准箱线图通过四分位数四分位间距(IQR,Interquartile Range)来定义异常值。具体来说,异常值的定义标准如下:

箱线图的组成部分:

  • 第一四分位数 (Q1): 将数据按升序排列后,位于25%位置的数据称为第一四分位数,即数据的下四分位。
  • 第三四分位数 (Q3): 位于75%位置的数据称为第三四分位数,即数据的上四分位。
  • 四分位间距 (IQR): 是 Q3 和 Q1 之间的差值,公式为:IQR=Q3Q1
  • 上下须线: 箱线图中的上下须线通常延伸到数据范围内的最小值和最大值,但这些值不包括异常值。须线的最大长度一般不超过 1.5 倍的 IQR。

异常值的定义标准:
在箱线图中,异常值通常定义为:低于 Q1 - 1.5 × IQR 的数据点;高于 Q3 + 1.5 × IQR 的数据点。

数学表达式:

  • 下界:任何数据点小于 Q11.5×IQR 的数据点被视为下侧异常值
  • 上界:任何数据点大于 Q3+1.5×IQR 的数据点被视为上侧异常值

举例:

假设数据集的四分位数 Q1=25Q3=75,四分位间距 IQR=50

  • 下界 = 25(1.5×50)=50
  • 上界 = 75+(1.5×50)=150

因此,在此数据集中,小于 -50 或大于 150 的数据点会被视为异常值。

异常值在箱线图中的表示:异常值通常用单独的表示,而不是作为箱体或须线的一部分。图中的点就是那些符合上述标准的异常值。

2.3 示例

参看上面异常点的说明,可知下图那些点是异常点。

三、案例分析

案例1:学生成绩分布

不同学年、不同科目的学生成绩也是箱线图的常见应用场景。下图中我们可以看到学生的英语成绩相对其它科目普遍较好,而数学则大部分都在80分以下。

案例2:吸烟者和小费金额之间的箱线图

上图展示了“吸烟者(smoker)”与“小费金额(tip)”之间的箱线图,按不同的天数(day)分类,蓝色表示非吸烟者,红色表示吸烟者。图中上方和下方的单独点为异常点,也就是离群点。根据箱线图中离群点的定义,这些点位于箱线图上下须线之外,即超过了Q3+1.5×IQR 或低于 Q11.5×IQR的部分。具体解释如下:
周日(Sun)和周六(Sat):蓝色和红色的离群点较多,意味着无论是否吸烟,在这两天里都存在一些顾客给了特别高的小费(例如图中可见的小费金额达到 8 或 10 的点)。
周四(Thur):只有红色(吸烟者)有一个离群点,这表明在周四时,有少数吸烟者给出了较大的小费,超过了典型范围。
周五(Fri):没有明显的离群点,这说明在这一天,吸烟者和非吸烟者给的小费都集中在正常范围内,数据较为均匀。
总的来说,这些离群点代表的是给出异常高小费的顾客,他们的行为与大多数顾客不同。

案例3:Iris鸢尾花箱线图

异常值处理(均值填充)展示

# 加载必要的库
library(ggplot2)
library(dplyr)

# 数据导入,R中自带 iris 数据集
train <- iris

# 数据清洗:用众数填充缺失值,并删除重复数据
train[is.na(train)] <- as.numeric(names(which.max(table(train))))
train <- distinct(train)

# 提取列名
a <- colnames(train)[1:4]  # 去掉分类标签列 (Species)
train_matrix <- as.matrix(train[, 1:4])  # 转换为矩阵格式,去除Species列
newtrain <- train_matrix  # 深拷贝

# 异常值检测与处理(用均值替换异常值)
for (i in 1:ncol(train_matrix)) {
  X <- train_matrix[, i]
  q1 <- quantile(X, 0.25)
  q3 <- quantile(X, 0.75)
  qr <- q3 - q1
  lower_tail <- q1 - 1.5 * qr
  upper_tail <- q3 + 1.5 * qr
  m <- mean(X)
  
  # 替换异常值
  X[X > upper_tail | X < lower_tail] <- m
  newtrain[, i] <- X
}

# 图像绘制
par(mfrow = c(1, 2))  # 设置画布为1行2列
boxplot(train_matrix, main = "处理前", col = c("pink", "lightblue", "lightgreen", "orange"), names = a)
boxplot(newtrain, main = "处理后", notch = TRUE, col = c("pink", "lightblue", "lightgreen", "orange"), names = a)

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import copy
import seaborn as sns

# 乱码解决
plt.rcParams["font.sans-serif"] = "SimHei"  # 汉字乱码的解决方法
plt.rcParams['axes.unicode_minus'] = False  # 用来正确显示负号

# 从seaborn数据集中直接导入iris数据
train = sns.load_dataset('iris')

# 确保没有字符串,并进行数据清洗
train.fillna(train.mode().iloc[0], inplace=True)  # 数据缺失值众数填充
train.drop_duplicates(inplace=True)  # 删除重复数据

# 表格第一行名称提取
a = list(train.columns)
train = np.array(train.iloc[:, :-1])  # 去除最后一列分类标签(species)
newtrain = copy.deepcopy(train)  # 深度拷贝

# 对数据异常值查找并对其进行平均值替换
for i in range(train.shape[1]):
    X = copy.deepcopy(train[:, i])  # 深度拷贝
    q1 = np.quantile(X, 0.25)  # 分位数
    q3 = np.quantile(X, 0.75)
    qr = q3 - q1
    Lower_tail = q1 - 1.5 * qr
    Upper_tail = q3 + 1.5 * qr
    m = np.mean(X)  # 平均值填充
    for j in range(len(X)):
        if X[j] > Upper_tail or X[j] < Lower_tail:
            X[j] = m
    newtrain[:, i] = copy.deepcopy(X)

# 图像绘制
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))

# 画箱线图
bplot1 = axes[0].boxplot(train, vert=True, patch_artist=True, meanline=False)
bplot2 = axes[1].boxplot(newtrain, vert=True, notch=True, patch_artist=True, meanline=False)

# 颜色填充
colors = ['pink', 'lightblue', 'lightgreen', 'orange', 'red']
for bplot in (bplot1, bplot2):
    for patch, color in zip(bplot['boxes'], colors):
        patch.set_facecolor(color)

# 图像修饰
biaoti = ['处理前', '处理后']
for k in range(len(axes)):
    axes[k].set_xlabel('类别')  # 设置x轴名称
    axes[k].set_ylabel('数值')  # 设置y轴名称
    axes[k].set_title("{}".format(biaoti[k]), fontsize=10)  # 标题填充,fontisize为字体大小

plt.setp(axes, xticks=[1, 2, 3, 4], xticklabels=a[:-1])  # 加刻度线名称,不包括分类标签
plt.show()

总结

异常值是统计分析中不可忽视的一部分,它们可能会显著影响分析结果,因此有效的异常值检测和处理是确保分析结果可靠性的重要步骤。通过结合各种检测方法,如箱线图、Z值检验、MAD法等,我们可以识别出异常数据点。处理异常值时,需根据具体情况灵活选择删除、替换、数据变换或采用鲁棒统计方法。同时,在处理过程中需谨慎对待,尤其是要结合数据的背景和领域知识,确保对异常值的处理是合理且不会遗漏有价值的信息。

参考文献

  1. 箱线图怎么判断异常值_箱线图
  2. 快速识别异常值,箱线图分析来帮你
  3. 数据分析--异常值处理
posted @   郝hai  阅读(3943)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示