使用Python检测并删除离群值

离群值是一个数据项/对象,它明显偏离其余的(所谓的正常)对象。它们可能由测量或执行错误引起。离群点检测的分析被称为离群点挖掘。检测离群值的方法有很多,删除过程与从pandas的数据框中删除数据项相同。

离群值检测和删除

在这里,pandas数据框架用于更现实的方法,因为现实世界的项目需要检测数据分析步骤中出现的离群值,相同的方法可以用于列表和序列类型的对象。

python 复制代码
# Importing
import sklearn
from sklearn.datasets import load_diabetes
import pandas as pd
import matplotlib.pyplot as plt

# Load the dataset
diabetics = load_diabetes()

# Create the dataframe
column_name = diabetics.feature_names
df_diabetics = pd.DataFrame(diabetics.data)
df_diabetics.columns = column_name
df_diabetics.head()

离群值可以使用可视化、在数据集上实现数学公式或使用统计方法来检测。下文将讨论所有这些问题。

离群值可视化

使用箱形图可视化离群值

它只需要一个简单的框和须就可以有效地捕获数据摘要。箱形图使用第25次、第50次和第75次采样总结了样本数据。人们可以通过查看数据集的箱形图来了解数据集(四分位数,中位数和离群值)。

python 复制代码
# Box Plot
import seaborn as sns
sns.boxplot(df_diabetics['bmi'])

在上图中,可以清楚地看到,高于10的值是离群值。

python 复制代码
# Position of the Outlier
import numpy as np
print(np.where(df_diabetics['bmi']>0.12))

输出

python 复制代码
(array([ 32, 145, 256, 262, 366, 367, 405]),)

使用散点图可视化离群值

当您有成对的数值数据,并且因变量对每个阅读自变量有多个值时,或者当尝试确定两个变量之间的关系时,使用该方法。在利用散点图的过程中,也可以将其用于离群值检测。

要绘制散点图,需要两个变量以某种方式彼此相关。因此,这里使用的是"每个城镇的非零售业务面积比例"和"每10,000美元的全额财产税税率",其列名分别为"INDUS"和"TAX"。

python 复制代码
# Scatter plot
fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(df_diabetics['bmi'], df_diabetics['bp'])

# x-axis label
ax.set_xlabel('(body mass index of people)')

# y-axis label
ax.set_ylabel('(bp of the people )')
plt.show()

查看图表可以总结出大多数数据点都在图表的左下角,但很少有点正好相反,即图表的右上角。右上角的那些点可以被视为离群值。

使用近似可以说所有那些x>20和y>600的数据点都是离群值。下面的代码可以获取满足这些条件的所有点的精确位置。

BMI和BP列合并的离群值

在这里,NumPy的np.where()函数用于在DataFrame df_diabetics中查找条件(df_diabetics['bmi'] > 0.12) & (df_diabetics['bp'] < 0.8) 为真的位置(索引)。该条件检查bmi大于0.12且bp小于0.8的离群值。输出提供DataFrame中离群值位置的行和列索引。

python 复制代码
# Position of the Outlier
print(np.where((df_diabetics['bmi'] > 0.12) & (df_diabetics['bp'] < 0.8)))

输出

python 复制代码
(array([ 32, 145, 256, 262, 366, 367, 405]),)

Z-score

Z-score也称为标准分数。该值/分数有助于理解数据点距离平均值有多远。并且在设置阈值之后,可以利用数据点的z得分值来定义离群值。

Zscore = (data_point -mean) / std. deviation

在本例中,我们使用SciPy stats模块中的zscore函数计算DataFrame df_diabetics中"age"列的Z分数。生成的数组z包含"age"列中每个数据点的绝对Z分数,指示每个值与平均值的标准差。

python 复制代码
# Z score
from scipy import stats
import numpy as np
 
z = np.abs(stats.zscore(df_diabetics['age']))
print(z)

输出

python 复制代码
[0.80050009 0.03956713 1.79330681 1.87244107 0.11317236 1.94881082
 0.9560041  1.33508832 0.87686984 1.49059233 2.02518057 0.57139085
 0.34228161 0.11317236 0.95323959 1.1087436  0.11593688 1.48782782
 0.80326461 0.57415536 1.03237385 1.79607132 1.79607132 0.95323959
 1.33785284 1.41422259 2.25428981 0.49778562 1.10597908 1.41145807
 1.26148309 0.49778562 0.72413034 0.6477606  0.34228161 1.02960933
 0.26591186 0.19230663 0.03956713 0.03956713 0.11317236 2.10155031
 1.26148309 0.41865135 0.95323959 0.57139085 1.18511334 1.64333183                                                                                       
 1.41145807 0.87963435 0.72413034 1.25871858 1.1087436  0.19230663
 1.03237385 0.87963435 0.87963435 0.57415536 0.87686984 1.33508832
 1.49059233 0.87963435 0.57415536 0.72689486 1.41145807 0.9560041
 0.19230663 0.87686984 0.80050009 0.34228161 0.03956713 0.03956713
 1.33508832 0.26591186 0.26591186 0.19230663 0.65052511 2.02518057
 0.11317236 2.17792006 1.48782782 0.26591186 0.34504612 0.80326461
 0.03680262 0.95323959 1.49059233 0.95323959 1.1087436  0.9560041
 0.26591186 0.95323959 0.42141587 1.03237385 1.64333183 1.49059233
 1.18234883 0.57415536 0.03680262 0.03956713 0.34228161 0.34228161]

上面的输出只是部分数据的快照;列表的实际长度(z)是506,即行数。它打印列的每个数据项的z得分值

现在,为了定义离群值,选择通常为3.0的阈值。由于99.7%的数据点位于+/- 3标准差之间(使用高斯分布方法)。

Z值大于2的情况下

在这个例子中,我们设置了一个阈值2,然后使用NumPy的np.where()来标识Z分数数组z中绝对Z分数大于指定阈值(2)的位置(索引)。它根据Z分数标准在"年龄"列中打印离群值的位置。

python 复制代码
threshold = 2
 
# Position of the outlier
print(np.where(z > 2))

输出

python 复制代码
(array([ 10,  26,  41,  77,  79, 106, 131, 204, 223, 226, 242, 311, 321,344, 374, 402]),)

IQR(四分位数间距)

四分位数间距(IQR)是研究领域中最常用和最可信的离群值发现方法。

IQR = Quartile3 - Quartile1

语法: numpy.percentile(arr, n, axis=None, out=None)

主要参数:

arr:输入数组。 n:百分位数值。

在本例中,我们计算DataFrame df_diabetics中"bmi"列的四分位距(IQR)。它首先使用中点法计算第一四分位数(Q1)和第三四分位数(Q3),然后计算IQR作为Q3和Q1之间的差值,提供"bmi"列中中间50%数据的分布度量。

python 复制代码
# IQR
Q1 = np.percentile(df_diabetics['bmi'], 25, method='midpoint')
Q3 = np.percentile(df_diabetics['bmi'], 75, method='midpoint')
IQR = Q3 - Q1
print(IQR)

输出

python 复制代码
0.06520763046978838

为了定义离群值基础值定义为高于和低于数据集的正常范围,即上限和下限,定义上限和下限(考虑1.5*IQR值):

upper = Q3 +1.5*IQR

lower = Q1 -- 1.5*IQR

在上述公式中,根据统计学,采用IQR的0.5比例放大(new_IQR = IQR + 0.5*IQR),以考虑高斯分布中2.7标准差之间的所有数据。

python 复制代码
# Above Upper bound
upper = Q3+1.5*IQR
upper_array = np.array(df_diabetics['bmi'] >= upper)
print("Upper Bound:", upper)
print(upper_array.sum())

# Below Lower bound
lower = Q1-1.5*IQR
lower_array = np.array(df_diabetics['bmi'] <= lower)
print("Lower Bound:", lower)
print(lower_array.sum())

输出

python 复制代码
Upper Bound: 0.12879000811776306
3
Lower Bound: -0.13204051376139045
0

去除离群值

为了移除离群值,必须遵循使用其在数据集中的确切位置从数据集中移除条目的相同过程,因为在检测离群值的所有上述方法中,最终结果是根据所使用的方法满足离群值定义的所有那些数据项的列表。

dataframe.drop(row index,inplace=True)

上面的语法可以用来从数据集中删除一行,给定要删除的row_indexes。Inplace =True用于告诉Python在原始数据集中进行所需的更改。row_index只能是一个值或值列表或NumPy数组,但必须是一维的。

例:

python 复制代码
df_diabetics.drop(lists[0],inplace = True)

基于IQR的离群点检测与删除

在这个例子中,我们使用四分位距(IQR)方法来检测和删除糖尿病数据集的"bmi"列中的离群值。它基于IQR计算上限和下限,使用布尔数组识别离群值索引,然后从DataFrame中删除相应的行,从而生成排除离群值的新DataFrame。打印DataFrame的前后形状以进行比较。

python 复制代码
# Importing
import sklearn
from sklearn.datasets import load_diabetes
import pandas as pd

# Load the dataset
diabetes = load_diabetes()

# Create the dataframe
column_name = diabetes.feature_names
df_diabetes = pd.DataFrame(diabetes.data)
df_diabetes .columns = column_name
df_diabetes .head()
print("Old Shape: ", df_diabetes.shape)

''' Detection '''
# IQR
# Calculate the upper and lower limits
Q1 = df_diabetes['bmi'].quantile(0.25)
Q3 = df_diabetes['bmi'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5*IQR
upper = Q3 + 1.5*IQR

# Create arrays of Boolean values indicating the outlier rows
upper_array = np.where(df_diabetes['bmi'] >= upper)[0]
lower_array = np.where(df_diabetes['bmi'] <= lower)[0]

# Removing the outliers
df_diabetes.drop(index=upper_array, inplace=True)
df_diabetes.drop(index=lower_array, inplace=True)

# Print the new shape of the DataFrame
print("New Shape: ", df_diabetes.shape)

输出

python 复制代码
Old Shape:  (442, 10)
New Shape:  (439, 10)
相关推荐
小码的头发丝、21 分钟前
Django中ListView 和 DetailView类的区别
数据库·python·django
Chef_Chen1 小时前
从0开始机器学习--Day17--神经网络反向传播作业
python·神经网络·机器学习
千澜空1 小时前
celery在django项目中实现并发任务和定时任务
python·django·celery·定时任务·异步任务
斯凯利.瑞恩2 小时前
Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户附数据代码
python·决策树·随机森林
yannan201903132 小时前
【算法】(Python)动态规划
python·算法·动态规划
蒙娜丽宁2 小时前
《Python OpenCV从菜鸟到高手》——零基础进阶,开启图像处理与计算机视觉的大门!
python·opencv·计算机视觉
光芒再现dev2 小时前
已解决,部署GPTSoVITS报错‘AsyncRequest‘ object has no attribute ‘_json_response_data‘
运维·python·gpt·语言模型·自然语言处理
好喜欢吃红柚子2 小时前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
小馒头学python2 小时前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
神奇夜光杯3 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长