異常值也稱離群點,異常值分析也稱離群點分析。
1. 簡單統計量分析
最常用的事最大值和最小值,超出合理范圍為異常。如客戶年齡為199歲,該值為異常。
2. 3σ原則
(1)、如果數據服從正態分布,在3σ原則下,異常值被定義為與平均值偏差超過3倍標准差的值。
在正態分布情況下,距離平均值3α之外的值出現的概率為 P(|x-μ|>3σ) ≤ 0.003,屬於極個別的小概率事件。
(2)、如果數據不服從正態分布,也可以用遠離平均值的多少倍標准差來描述。
3. 箱型圖判斷
箱型圖提供識別異常值的一個標准:異常值被定義為小於 QL-1.5IQR 或 大於Qu+1.5IQR的值。
QL為下四分位數,表示全部觀察值中有四分之一的數據比它小;
Qu為上四分位數,表示全部觀察值中有四分之一的數據比它大;
IQR為四分位數間距,是上四分位與下四分位之差,其中包含了觀察值的一半。
import pandas as pd catering_sale = './catering_sale.xls' # 餐飲數據 data = pd.read_excel(catering_sale, index_col = u'日期') # 讀取數據,指定“日期”列為索引列 import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來顯示中文標簽 plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號 plt.figure() p = data.boxplot() # 畫箱線圖,直接使用DataFrame方法 x = p['fliers'][0].get_xdata() # 'flies'為異常值的標簽 y = p['fliers'][0].get_ydata() y.sort() # 用annotate添加注釋 # 其中有些相近的點,注釋會出現重疊,難以看清,需要一些技巧來控制 # 以下參數都是經過調試的,需要具體問題具體調試 for i in range(len(x)): if i>0: plt.annotate(y[i], xy = (x[i], y[i]), xytext=(x[i]+0.05 - 0.8/(y[i]-y[i-1]),y[i])) else: plt.annotate(y[i], xy = (x[i], y[i]), xytext=(x[i]+0.08,y[i])) plt.show()
箱型圖中超過上下界的8個銷售額數據可能為異常值。結合業務把865、4060.3、4065.2歸為正常值,將22、51、60、6607.4、9106.44歸為異常值。最后確定過濾規則為:400以下5000以上為異常值。
4. Z-Score判斷
這里使用Z標准化的閾值作為判斷標准,當標准化后的得分超過閾值為異常。
import pandas as pd # 生成異常數據 df = pd.DataFrame({'coll' : [1, 120, 3, 5, 2, 12, 13], 'col2' : [12, 17, 31, 53, 22, 32, 43]}) print(df) # 通過Z-Score方法判斷異常值 # pandas中,如果b = a,則b is a。所以想要復制它的值,但不關聯,就必須深度復制,b = a.copy()。 df_zscore = df.copy() # 通過df.copy()復制一個原始數據框的副本用來存儲Z-Score標准化后的得分 cols = df.columns # 獲得數據框的列名 for col in cols: df_col = df[col] # 得到每列的值 z_score = (df_col - df_col.mean())/df_col.std() # 計算每列的Z-score得分 df_zscore[col] = z_score.abs() > 2.2 # 判斷Z-score得分是否大於2.2,如果是則是True,否則為False print(df_zscore)
閥值的設定是確定異常與否的關鍵,通常當閥值大於2時,已經是相對異常的表現值。
上述代碼以空行分為3部分:
- 導入Pandas庫.
- 生成異常數據.
- 缺失值判斷過程.
總結: 如何判斷異常值
對於有固定業務規則的可直接套用業務規則。
對於沒有固定業務規則的,除了上述4中簡單方法外,還可以采用常見的數學模型進行判斷:基於概率分布的模型(例如正態分布的標准差范圍)、基於聚類的方法(例如KMeans)、基於密度的方法(例如LOF)、基於分類的方法(例如KNN)、基於統計的方法(例如分位數法)等。