使用Python检测和删除异常值
离群点是指明显偏离其他(所谓的正常)对象的数据项/对象。它们可能是由测量或执行错误引起的。检测离群点的分析被称为离群点挖掘。检测离群点的方法有很多,去除过程是数据框架与从Pandas的数据框架中去除一个数据项一样。
在这里,pandas数据框架被用于一个更现实的方法,因为在现实世界的项目中,需要检测数据分析步骤中出现的异常值,同样的方法也可以用于列表和系列类型的对象。
数据集:
使用的数据集是波士顿住房数据集,因为它已经预装在sklearn库中。
# Importing
import sklearn
from sklearn.datasets import load_boston
import pandas as pd
import matplotlib.pyplot as plt
# Load the dataset
bos_hou = load_boston()
# Create the dataframe
column_name = bos_hou.feature_names
df_boston = pd.DataFrame(bos_hou.data)
df_boston.columns = column_name
df_boston.head()
输出:
数据集的一部分
检测离群值
离群值可以通过可视化、在数据集上实现数学公式或使用统计方法来检测。所有这些都将在下面讨论。
1. 可视化
它只用一个简单的方框和晶须就能有效地捕捉到数据的摘要。Boxplot使用第25、50和75个百分位数来总结样本数据。人们只需看一下数据集的boxplot,就可以深入了解(四分位数、中位数和离群值)。
# Box Plot
import seaborn as sns
sns.boxplot(df_boston['DIS'])
输出 :
波谱图-DIS列
在上图中,可以清楚地看到,10以上的数值是作为离群值。
# Position of the Outlier
print(np.where(df_boston['DIS']>10))
输出:
Outlier’s Index
例子2:使用 ScatterPlot
当你有成对的数字数据时,或当你的因变量对每个读自变量有多个值时,或当试图确定两个变量之间的关系时,就会用到它。在利用散点图的过程中,人们还可以用它来检测离群点。
要绘制散点图,需要两个相互之间有某种联系的变量。因此,这里使用了 “每个城镇的非零售商业亩数比例 “和 “每10,000美元的全额财产税率”,其列名分别为 “INDUS “和 “TAX”。
# Scatter plot
fig, ax = plt.subplots(figsize = (18,10))
ax.scatter(df_boston['INDUS'], df_boston['TAX'])
# x-axis label
ax.set_xlabel('(Proportion non-retail business acres)/(town)')
# y-axis label
ax.set_ylabel('(Full-value property-tax rate)/( $10,000)')
plt.show()
输出 :
观察图表可以总结出,大多数数据点都在图表的左下角,但也有少数点正好相反,即在图表的右上角。这些位于右上角的点可以被视为离群点。
使用近似法可以说所有那些x>20和y>600的数据点都是离群值。下面的代码可以获取所有满足这些条件的点的确切位置。
# Position of the Outlier
print(np.where((df_boston['INDUS']>20) & (df_boston['TAX']>600)))
输出 :
2. Z-score
Z-分也被称为标准分。这个值/分数有助于了解数据点离平均值有多远。在设置了一个阈值后,人们可以利用数据点的Z值来定义离群值。
Zscore = (data_point -mean) / std. deviation
# Z score
from scipy import stats
import numpy as np
z = np.abs(stats.zscore(df_boston['DIS']))
print(z)
输出 :
列表中的一部分(z)
上面的输出只是部分数据的快照;list(z)的实际长度是506,也就是行数。它打印了列中每个数据项的Z分数值
现在要定义一个离群的阈值,一般选择3.0。因为99.7%的数据点位于+/-3标准差之间(使用高斯分布方法)。
threshold = 3
# Position of the outlier
print(np.where(z > 3))
输出:
Outlier’s Index
3. IQR (Inter Quartile Range)
IQR(四分位数范围)四分位数范围的方法来寻找异常值,是研究领域中最常用和最值得信赖的方法。
IQR = Quartile3 – Quartile1
# IQR
Q1 = np.percentile(df_boston['DIS'], 25,
interpolation = 'midpoint')
Q3 = np.percentile(df_boston['DIS'], 75,
interpolation = 'midpoint')
IQR = Q3 - Q1
输出:
定义离群值的基础是定义高于和低于数据集的正常范围,即上界和下界,定义上界和下界(考虑1.5*IQR值)。
upper = Q3 +1.5*IQR
lower = Q1 – 1.5*IQR
在上述公式中,根据统计学,采取了IQR的0.5扩展(new_IQR = IQR + 0.5*IQR),以考虑高斯分布中2.7标准差之间的所有数据。
# Above Upper bound
upper = df_boston['DIS'] >= (Q3+1.5*IQR)
print("Upper bound:",upper)
print(np.where(upper))
# Below Lower bound
lower = df_boston['DIS'] <= (Q1-1.5*IQR)
print("Lower bound:", lower)
print(np.where(lower))
输出:
定义的界线和与界线相关的离群点的索引
去除异常值
对于移除离群点,我们必须遵循同样的过程,使用它在数据集中的确切位置从数据集中移除一个条目,因为在上述所有检测离群点的方法中,最终结果是所有那些根据所使用的方法满足离群点定义的数据项的列表。
dataframe.drop( row_index, inplace = True
上面的代码可以用来从数据集中删除一条记录,给定要删除的row_indexes。Inplace =True用于告诉python在原始数据集中进行所需的修改。 row_index可以是一个值或值的列表或NumPy数组,但它必须是一维的。
示例:
df_boston.drop(lists[0],inplace = True)
完整的代码:使用IQR检测异常值并将其删除。
# Importing
import sklearn
from sklearn.datasets import load_boston
import pandas as pd
# Load the dataset
bos_hou = load_boston()
# Create the dataframe
column_name = bos_hou.feature_names
df_boston = pd.DataFrame(bos_hou.data)
df_boston.columns = column_name
df_boston.head()
''' Detection '''
# IQR
Q1 = np.percentile(df_boston['DIS'], 25,
interpolation = 'midpoint')
Q3 = np.percentile(df_boston['DIS'], 75,
interpolation = 'midpoint')
IQR = Q3 - Q1
print("Old Shape: ", df_boston.shape)
# Upper bound
upper = np.where(df_boston['DIS'] >= (Q3+1.5*IQR))
# Lower bound
lower = np.where(df_boston['DIS'] <= (Q1-1.5*IQR))
''' Removing the Outliers '''
df_boston.drop(upper[0], inplace = True)
df_boston.drop(lower[0], inplace = True)
print("New Shape: ", df_boston.shape)
输出 :