在数据科学之旅中,经常需要处理各种数据集。例如,可能不需要对鸢尾花数据集进行数据清洗,但现实世界的数据集远非完美。数据集中存在许多缺陷,需要在拟合任何模型之前进行处理。如果数据没有得到妥善处理,可能会导致偏见,结果也将不可靠。这就是探索性数据分析发挥作用的地方。
探索性数据分析涉及多个步骤,如识别所有变量及其数据类型、单变量和双变量分析、处理缺失值、处理异常值等。在任何模型构建过程中,建议不要跳过探索性数据分析步骤。探索性数据分析中最重要的步骤之一是异常值检测。异常值是极端值,可能与其他数据点不匹配。它们可能是由于各种错误而进入数据集的。处理异常值有多种方法,但需要根据拥有的数据集选择最佳方法。
“在普通人的人群中,一个名人就是一个异常值。”
上述陈述可能已经给出了关于什么是异常值的公平线索。异常值是那些远离其他数据点的数据点,就像突然增加或减少很多倍一样,或者简单地说,异常值是数据集中所有其他值范围之外的值。例如,在医院测量病人的体温时,有一个条目是988摄氏度,这显然是不正确的。可能是缺少小数点,应该是98.8而不是988。
另一个例子是在测量高中学生体重时,有一个条目体重为1234,这是非常不可能的。它可能是数据输入错误。异常值不一定是错误的条目,在某些情况下,它可能是某个实验的结果,但由数据科学家决定。异常值的范围取决于业务问题,并且可以根据案例而变化。最好在将数据点称为异常值之前与业务利益相关者讨论。异常值需要特别关注,以确保它们不会在模型结果中引起任何问题。
如果在进行探索性数据分析的第一步时没有处理异常值,可能会导致结果中的偏见。偏见可能会产生许多不利影响,导致糟糕的业务决策,最终导致业务损失。
有无数的机器学习算法可以处理异常值,其中以下是最常用的,让详细看看每个算法并举例。
Z分数测试是检测异常值最常用的方法之一。它测量观察值与平均值的标准差数。Z分数为1.5表示观察值比平均值高出1.5个标准差,-1.5表示观察值比平均值低1.5个标准差或更低。
Z分数 = (x - 平均值) / 标准差
其中x是数据点
如果观察值的Z分数为3或更多,则通常被视为异常或异常值。
让使用上面的表格,通过计算他们的Z分数来检测学生体重中的异常值。
import pandas as pd
import scipy.stats as stats
student_info = pd.read_excel('student_weight.xlsx')
z_score = stats.zscore(student_info['weights(in Kg)'])
print(z_score)
输出:
[-0.30359971 -0.32843404 -0.35326838 -0.34085121 -0.37189413 -0.34085121
-0.29739113 2.99936649 -0.32843404 -0.33464263]
可以清楚地看到,条目588是异常值,这一点通过Z分数测试得到了确认。
箱线图通过将数据点划分为不同的四分位数来显示数据点的分布。箱线图标记了数据集的最小值、最大值、中位数、第一和第三四分位数。这些百分位数也被称为下四分位数、中位数和上四分位数。这是检测异常值的视觉方法之一。任何位于盒子和须之外的异常值都可以被视为异常值。
import matplotlib.pyplot as plt
fig = plt.figure(figsize =(10, 7))
plt.boxplot(student_info['weights(in Kg)'])
plt.show()
下图显示了学生体重数据集的箱线图。有一个观察值远离盒子和须,表明这个数据点是异常值。
隔离森林算法是一个易于实现但功能强大的异常值检测选择。隔离森林基于决策树算法,它通过选择一个随机特征和一个在所选特征的最大值和最小值之间的分割值来从数据集中隔离异常值。
当数据集庞大且具有许多特征时,隔离森林方法比其它方法更受青睐,因为它使用的内存比其它技术少。
from sklearn.ensemble import IsolationForest
model=IsolationForest(n_estimators=50, max_samples='auto', contamination=float(0.1),max_features=1.0)
model.fit(student_info[['weights(in Kg)']])
student_info['scores']=model.decision_function(student_info[['weights(in Kg)']])
student_info['anomaly']=model.predict(student_info[['weights(in Kg)']])
anomaly=student_info.loc[student_info['anomaly']==-1]
anomaly_index=list(anomaly.index)
print(anomaly)
输出:
# 输出结果将显示异常值的详细信息
from sklearn.cluster import DBSCAN
model = DBSCAN(eps=0.8, min_samples=10).fit(student_info[['weights(in Kg)']])
X = model.labels_
plt.scatter(student_info['weights(in Kg)'], student_info['student_name'], marker='o')
plt.xlabel('Students', fontsize=16)
plt.ylabel('Weights', fontsize=16)
plt.title('Students Vs Weights', fontsize=20)
plt.show()