文章目錄
- 基于3σ原則檢測異常值
- 代碼實現
- 測試
- 基于箱型圖檢測異常值
- 異常值的處理
基于3σ原則檢測異常值
3σ原則,又稱拉依達準則。是指假設一組檢測數據只含有隨機誤差。對其進行計算處理得到標準偏差,按一定概率確定一個區間,凡是超過這個區間的誤差都是粗大誤差,在此誤差范圍內的數據應予以剔除。
正態分布概率公式中,σ表示標準差,μ表示平均數,f(x)表示正態分布函數。
正態分布公式
正態曲線下,
橫軸區間(μ-σ,μ+σ)內的面積為68.268949%。
P{|X-μ|<σ}=2Φ(1)-1=0.6826
橫軸區間(μ-2σ,μ+2σ)內的面積為95.449974%。
P{|X-μ|<2σ}=2Φ(2)-1=0.9544
橫軸區間(μ-3σ,μ+3σ)內的面積99.730020%。
P{|X-μ|<3σ}=2Φ(3)-1=0.9974
由于“小概率事件”和假設檢驗的基本思想 “小概率事件”通常指發生的概率小于5%的事件,認為在一次試驗中該事件是幾乎不可能發生的。
由上可知,X落在(μ-3σ,μ+3σ)以外的概率小于千分之三,在實際問題中常認為相應的事件是不會發生的,基本上可以把區間(μ-3σ,μ+3σ)看作是隨機變量X實際可能的取值區間,超過這個區間的就屬于異常值,應予以剔除。
代碼實現
import numpy as np
import pandas as pddef three_sigma(ser1): # ser1表示傳入DataFrame的某一列mean_value = ser1.mean() # 求平均值std_value = ser1.std() # 求標準差rule = (mean_value - 3 * std_value > ser1) | (ser1.mean() + 3 * ser1.std() < ser1)# 位于(u-3std,u+3std)區間的數據是正常的,不在這個區間的數據為異常的# 一旦發現有異常值,就標注為True,否則標注為Falseindex = np.arange(ser1.shape[0])[rule] # 返回異常值的位置索引outrange = ser1.iloc[index] # 獲取異常數據return outrange
測試
將符合正態分布的包含異常值的測試數據保存在D:\數據分析\data.xlsx中。使用Pandas的read_excel()函數從文件中讀取數據,并轉換為DataFrame對象。之后分別對data中的A列數據和B列數據進行檢測。
data = pd.read_excel(r'D:\數據分析\data.xlsx')
print(data)
print(three_sigma(data['A']))
print(three_sigma(data['B']))
輸出結果:
Unnamed: 0 A B
0 0 1 2
1 1 2 3
2 2 3 8
3 3 4 5
4 4 5 6
5 5 560 7
6 6 2 8
7 7 3 9
8 8 4 0
9 9 5 3
10 10 3 4
11 11 2 5
12 12 4 6
13 13 5 7
14 14 5 2
15 15 23 4
16 16 2 55 560
Name: A, dtype: int64Series([], Name: B, dtype: int64)
基于箱型圖檢測異常值
箱型圖是一種用作顯示一組數據分散情況的統計圖。在箱型圖中,異常值通常被定義為小于QL-1.5QR或大于QU+1.5IQR的值。其中:
QL:下四分位數,表示全部觀察值中有四分之一的數據取值比它大。
QU:上四分位數,表示全部觀察值中有四分之一的數據取值比它小。
IQR:四分位數間距,是QU與QL之差,其間包含了全部觀察值的一半。
箱型圖是根據實際數據進行繪制,對數據沒有任何要求(3σ原則要求數據服從正態分布或近似正態分布)。箱型圖判斷異常值的標準是以四分位數和四分位距為基礎的。
Pandas中提供了一個專門用來繪制箱型圖的boxplot()方法。
df = pd.DataFrame({'A': [1, 2, 3, 4],'B': [2, 3, 4, 5],'C': [1, 4, 7, 4],'D': [1, 5, 30, 3]})
print(df.boxplot(column=['A', 'B', 'C', 'D']))
輸出結果:
異常值的處理
檢測出異常值后,通常會才用如下四種方式處理這些異常值:
1、直接將含有異常值的記錄刪除
2、用具體的值來進行替換,可用前后兩個觀測值的平均值修正該異常值
3、不處理,直接在具有異常值的數據集上進行統計分析
4、視為缺失值,利用缺失值的處理方法修正該異常值
異常數據被檢測出來之后,需要進一步確認他們是否為真正的異常值,等確認完以后再決定選用哪種方法進行解決。
如果希望對異常值進行修改(執行操作2),則可以使用Pandas中replace()方法進行替換,該方法不僅可以對單個數據進行替換,也可以多個數據執行批量替換操作。
replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method=‘pad’)
部分參數:
to_replace:表示查找被替換值的方式
value:用來替換任何匹配to_replace的值,默認值為None
limit:表示前向或后向填充的最大尺寸間隙
regex:接收布爾值或與to_replace相同的類型,默認為False,表示是否將to_replace和value解釋為正則表達式
method:替換時使用的方法,pad/ffill表示前向填充,bfill表示后向填充
replace()方法的使用
print(df.replace(to_replace=30, value=3))
print(data.replace(to_replace=data.loc[5, ['A']], value=6))
輸出結果:
AxesSubplot(0.125,0.11;0.775x0.77)A B C D
0 1 2 1 1
1 2 3 4 5
2 3 4 7 3
3 4 5 4 3Unnamed: 0 A B
0 0 1 2
1 1 2 3
2 2 3 8
3 3 4 5
4 4 5 6
5 5 6 7
6 6 2 8
7 7 3 9
8 8 4 0
9 9 5 3
10 10 3 4
11 11 2 5
12 12 4 6
13 13 5 7
14 14 5 2
15 15 23 4
16 16 2 5