赞
踩
通常,咱们做数据挖掘的时候经常免不了会遇到异常值检测或者异常值处理等步骤,那么什么是异常值呢?如何检测数据中是否存在异常值?如何处理数据中的异常值?本文专门探究一下这些问题。
异常值又称离群点,是指那些在数据集中存在的不合理的值,需要注意的是,不合理的值是偏离正常范围的值,不是错误值。
异常值出现的原因:数据集中的异常值可能是由于传感器故障、人工录入错误或异常事件导致。
异常值的检测通常有简单统计分析、3σ原则、箱型图、聚类等方法,以下详细对各个方法进行逐一说明。
最常用的统计量是最大值和最小值,用来判断这个变量的取值是否超出合理的范围。在pandas中,一般使用describ属性就可以查看相关的统计量。
# 全国房价数据统计
df_dropna = df[~df.price.isna()].reset_index(drop=True) # 首先剔除NA值
df_dropna.price.describe()
3σ原则的前提假设是数据集符合正态分布(高斯分布),如下图:
观察上图容易得出以下数据分布情况:
可以认为,数据存在随机误差,其取值几乎全部集中在(μ-3σ, μ+3σ)区间内,超出这个范围的可能性仅占不到0.3%,那么误差超过这个区间的值就识别为异常值了。
实际上,大部分真实的数据并不满足这一条件,我们就需要先对原始数据集进行Z-score变换,使用原始数据的均值(μ)和标准差(σ)进行数据的标准化。经过处理的数据也将服从标准正态分布,其均值为0,标准差为1,故3σ原则又被称为Z-score method。
Z = x − μ σ Z = \frac{x-μ}{σ} Z=σx−μ
经过Z-score标准化后得到符合正态分布的数据,我们就可以使用3σ原则来处理数据了。演示代码如下:
# 观察原始房价数据分布情况 import matplotlib.pyplot as plt s = df_dropna.price fig = plt.figure(figsize=(6, 6)) # 创建自定义图像 ax1 = fig.add_subplot(2,1,1) # 创建子图1 ax1.scatter(s.index, s.values) # 绘制散点图 plt.grid() # 添加网格 ax2 = fig.add_subplot(2,1,2) # 创建子图2 s.hist(bins=30, alpha=0.5, ax=ax2) # 绘制直方图 s.plot(kind='kde', secondary_y=True, ax=ax2) # 绘制密度图,使用双坐标轴 plt.grid() plt.show() # 显示自定义图像 # ######################################### # Z-score变换 _std = df_dropna.price.std() _mean = df_dropna.price.mean() df_dropna['z_price'] = df_dropna.price.map(lambda x: (x-_mean)/_std) # 3σ原则检测异常值 _mean = 0 _std = 1 mark = (_mean-3*_std>df_dropna['z_price']) | (df_dropna['z_price']>_mean+3*_std) df_dropna[mark] # 异常数据
根据实际业务需求,若数据不服从正态分布,也可以不做标准化处理,可以用远离平均值的多少倍标准差来描述(这就使Z-score方法可以适用于不同的业务场景,只是需要根据经验来确定 kσ 中的k值,这个k值就可以认为是阈值),演示代码如下:
# Z-score方法检测异常值(阈值k=3)
_mean = df_dropna.price.mean()
_std = df_dropna.price.std()
mark = (_mean-3*_std>df_dropna.price) | (df_dropna.price>_mean+3*_std)
df_dropna[mark] # 异常数据
该方法也被称为 中位数绝对偏差法。它类似于Z-score方法,只是参数有所变化。由于平均值和标准差受异常值的影响很大,因此我们使用中位数和中位数的绝对偏差来改变这个参数,公式如下:
R . Z . s c o r e = 0.6745 × ( x − M e d i a n ) M A D w h e r e M A D = m e d i a n ( ∣ x − M e d i a n ∣ ) R.Z.score = \frac{0.6745\times \left ( x-Median\right ) }{MAD} \\ where \quad MAD=median(∣x−Median∣) R.Z.score=MAD0.6745×(x−Median)whereMAD=median(∣x−Median∣)
假设 x x x 服从标准正态分布,那么 M A D MAD MAD 会收敛于半正态分布的中位数,即正态分布的75%百分位,并且 N ( 0.75 ) ≃ 0.6745 N(0.75)≃0.6745 N(0.75)≃0.6745。计算出稳健Z分数后,可以根据以下异常值的判定准则:
演示代码:
# R.Z.score Method检测异常值
import numpy as np
import scipy
# 计算R.Z.score
med = np.median(df_dropna.price.values)
mad = scipy.stats.median_absolute_deviation(df_dropna.price.values)
r_z_score = df_dropna.price.map(lambda x: (0.6745*(x-med)) / (np.median(mad)))
# 判定异常值
mark = np.abs(r_z_price.values) > 3
df_dropna[mark] # 异常数据
箱型图提供了识别异常值的标准,异常值通常被定义为小于QL-1.5IQR或大于QU+1.5IQR的数据。QL称为下四分位数,表示全部值中有四分之一的数据取值比它小;QU称为上四分位数,表示全部值中有四分之一的数据取值比它大;IQR称为四分位数间距,是上四分位数QU与下四分位数QL之差。所以此方法又称为四分位距法,如下图。
# 箱型图可视化数据
import matplotlib.pyplot as plt
plt.boxplot(df_dropna.price)
plt.show()
# 四分位距法检测异常值
QL = df_dropna.price.quantile(0.25)
QU = df_dropna.price.quantile(0.75)
IQR = QU - QL
mark = (df_dropna.price < QL - 1.5*IQR) | (QU + 1.5*IQR< df_dropna.price)
df_dropna[mark] # 异常数据
该方法类似于IQR法。如果一个值超过了第99个百分位数的值,并且低于给定值的第1个百分位数,则被视为异常值。
演示代码如下:
# 截尾处理检测异常值
up = df_dropna.price.quantile(0.99)
low = df_dropna.price.quantile(0.01)
mark = (df_dropna.price < low) | (df_dropna.price > up)
df_dropna[mark] # 异常数据
DBSCAN是一种基于密度的聚类算法,它将数据集划分为高密度区域的子组,并将稀疏区域聚类识别为异常值。集群标记-1表示该集群包含离群值,其余集群没有离群值。这种方法类似于K-means聚类。DBSCAN在多元离群值检测中具有最佳的检测效果。DBSCAN需要两个参数:
使用以上2个参数我们就可以把每个数据点分类成:
如下图所示:
演示代码:
import pandas as pd
from sklearn.cluster import DBSCAN
def DBSCAN_outliers(df): # df是列数据
outlier_detection = DBSCAN(eps=2, metric='euclidean', min_samples=5)
clusters = outlier_detection.fit_predict(df.values.reshape(-1,1))
return clusters
它是一种聚类算法,属于集成决策树家族,在原理上类似于随机森林。
孤立随机森林的特点有以下几点:
演示代码:
from sklearn.ensemble import IsolationForest
import numpy as np
import pandas as pd
def IsolationForest_outliers(df): # df是列数据
iso = IsolationForest(behaviour='new', random_state=1, contamination='auto')
preds = iso.fit_predict(df.values.reshape(-1,1))
return preds
Grubbs’ test 是一个假设检验方法。
其统计量被定义为:
G c a l c u l a t e d = m a x ( ∣ X i − X ˉ ∣ ) S D G_{calculated}=\frac{max(|X_i - \bar{X}|)}{SD} Gcalculated=SDmax(∣Xi−Xˉ∣)
其中 X ˉ \bar{X} Xˉ 和 SD 分别代表样本均值和样本标准差。其临界值被定义为:
G c i t i c a l = N − 1 N ( t α / ( 2 N ) , N − 2 ) 2 N − 2 + ( t α / ( 2 N ) , N − 2 ) 2 G_{citical}=\frac{N-1}{\sqrt{N}} \sqrt{\frac{(t_{\alpha/(2N),N-2})^{2}}{N-2+(t_{\alpha/(2N),N-2})^{2}}} Gcitical=N N−1N−2+(tα/(2N),N−2)2(tα/(2N),N−2)2
如果估计值
G
c
a
l
c
u
l
a
t
e
d
G_{calculated}
Gcalculated > 临界值
G
c
r
i
t
i
c
a
l
G_{critical}
Gcritical,拒绝原假设,备选假设成立,即数据集中有一个值是异常值。
一下是演示代码:
import numpy as np import scipy.stats as stats def grubbs_test(x): n = len(x) mean_x = np.mean(x) std_x = np.std(x) numerator = max(abs(x-mean_x)) g_calculated = numerator / std_x print("Grubbs Calculated Value:", g_calculated) t_value = stats.t.ppf(1 - 0.05 / (2 * n), n - 2) g_critical = ((n - 1) * np.sqrt(np.square(t_value))) / (np.sqrt(n) * np.sqrt(n - 2 + np.square(t_value))) print("Grubbs Critical Value:", g_critical) if g_critical > g_calculated: print("From grubbs_test we observe that calculated value is lesser than critical value, Accept null hypothesis and conclude that there is no outliers\n") else: print("From grubbs_test we observe that calculated value is greater than critical value, Reject null hypothesis and conclude that there is an outliers\n")
数据可视化对于数据清理、数据挖掘、异常值和异常组的检测、趋势和集群识别等都很有用。下面是用于发现异常值的数据可视化图列表:
import pandas as pd import seaborn as sns from matplotlib import pyplot as plt from statsmodels.graphics.gofplots import qqplot def Box_plots(s): plt.figure(figsize=(10,4)) plt.title("Box Plot") sns.boxplot(s) plt.show() def hist_plots(s): plt.figure(figsize=(10,4)) plt.hist(s) plt.title("Histogram Plot") plt.show() def scatter_plots(s1, s2): fig, ax = plt.subplots(figsize=(10,4)) ax.scatter(s1, s2) ax.set_xlabel('Age') ax.set_ylabel('Fare') plt.title("Scatter Plot") plt.show() def dist_plots(s): plt.figure(figsize=(10,4)) sns.distplot(s) plt.title("Distribution plot") sns.despine() plt.show() def qq_plots(df): plt.figure(figsize=(10,4)) qqplot(s, line='s') plt.title("Normal QQPlot") plt.show()
异常值的存在对数据集的影响有以下方面:
所以当我们检测到数据中存在异常值时必须做适当的处理才会使得数据挖掘工作更加准确,一般的,异常值的处理方法有:删除值、改变值、插补法和分组处理。
直接将含有异常值的记录删除,通常有两种策略:整条删除和成对删除。这种方法最简单简单易行,但缺点也不容忽视,一是,在观测值很少的情况下,这种删除操作会造成样本量不足;二是,直接删除、可能会对变量的原有分布造成影响,从而导致统计模型不稳定。
# 删除异常值(使用3σ原则)
df_drop_outlier = df_dropna[~mark].reset_index(drop=True)
# 剔除异常值后的箱型图
import matplotlib.pyplot as plt
plt.boxplot(df_drop_outlier.price)
plt.show()
转换变量也可以消除异常值。这些转换后的值减少了由极值引起的变化。转换方法通常有:
这些技术将数据集中的值转换为更小的值,而且不会丢失数据。如果数据有很多极端值或倾斜,数据变换有助于使您的数据正常。但是这些技巧并不总是给你最好的结果。在所有这些方法中,box-cox变换给出了最好的结果。以下代码仅仅作为演示:
# Scalling from sklearn import preprocessing scaler = preprocessing.StandardScaler() result = scaler.fit_transform(df_dropna.price.values.reshape(-1,1)) # Log transformation import numpy as np result = np.log(df_dropna.price.values) # Cube root Transformation import numpy as np result = np.cbrt(df_dropna.price.values) # Box-Cox Transformation import scipy result, maxlog = scipy.stats.boxcox(df_dropna.price.values ,lmbda=None)
像缺失值的归责(imputation)一样,我们也可以归责异常值。在这种方法中,我们可以使用 平均值、中位数、零值 来对异常值进行替换。由于我们进行了输入,所以没有丢失数据。应选则合适的替换,这里提及一下,选择中值不受异常值的影响。以下代码仅仅作为演示。
# 均值替换异常值
_mean = df_dropna.price.mean()
df_dropna[mark] = _mean
# 中位数替换异常值
_median = df_dropna.price.median()
df_dropna[mark] = _median
# 0替换异常值
df_dropna[mark] = 0
发现两个相关的变量之间的变化模式,通过使数据拟合一个函数来平滑数据,也就是回归插补。
若是变量之间存在依赖关系,也就是 y = f ( x ) y=f(x) y=f(x),那么就可以设法求出依赖关系 f f f,再根据x来预测 y y y,这也是回归问题的实质。
实际问题中更常为见的假设是 p ( y ) = N ( f ( x ) ) p(y)=N(f(x)) p(y)=N(f(x)), N N N 为正态分布。假设 y y y 是观测值并且存在噪声数据,根据我们求出的 x x x 和 y y y 之间的依赖关系,再根据 x x x 来更新 y y y 的值,这样就能去除其中的随机噪声,这就是回归去噪的原理 。
也就是截尾处理,这其实也是一种插补方法。整行替换数据框里百分位数处于99%以上和1%以下的点:将99%以上的点值 = 99%的点值;小于1%的点值 = 1%的点值。
# 盖帽法处理异常值
up = df_dropna.price.quantile(0.99)
low = df_dropna.price.quantile(0.01)
df_dropna.loc[df_dropna.price > up, 'price'] = up
df_dropna.loc[df_dropna.price < low, 'price'] = low
剔除和替换异常值或多或至少会对数据有负面影响,我们也可以根据该异常值的性质特点,使用更加稳健模型来修饰,然后直接在原数据集上进行数据挖掘。
1.Outlier!!! The Silent Killer
2.数据清洗之异常值处理的常用方法
3.异常数据处理——3σ原则、箱线图
4.3sigma原则剔除异常值(极端值)
5.Python检验样本是否服从正态分布
6.Python pandas库和stats库计算偏度和峰度(附程序)
7.数据预处理——3sigma原则离群值处理
8.能力验证中稳健Z比分数的计算方法
9.六种常见变量标准化方法的优缺点和适用范围
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。