Python:异常值检测箱型图(附:正态分布3σ)
????????異常值檢測的方法有很多,通過數據分布圖型尋找異常值、算法模型(聚類、隨機森林等),我這里就是記錄一下工作中做初步的數據探查時用到的箱型圖檢測和正態分布檢測,這兩種都是根據數據分布情況來識別異常值的,沒有結合到業務的層面,在做初步的探查時還是高效且適用的。因為正態分布3σ的異常值檢測需要數據符合正態分布,現實情況中大部分數據都是雜亂無章的,因此重點使用的是箱型圖檢測。
1.箱型圖的優勢
(1)準確穩定地描繪出數據的離散分布情況且不需要服從特定的分布形式
箱形圖的繪制依靠實際數據,不需要事先假定數據服從特定的分布形式,沒有對數據作任何限制性要求,它只是真實直觀地表現數據形狀的本來面貌;
(2)異常值不會影響四分位數的確定
箱形圖判斷異常值的標準以四分位數和四分位距為基礎,四分位數具有一定的耐抗性,多達25%的數據可以變得任意遠而不會很大地擾動四分位數,所以異常值不能對這個標準施加影響,箱形圖識別異常值的結果比較客觀。
2.箱型圖的示意及符號說明
(圖片來源于網絡)
Qi所在位置=i(n+1)/4,其中i=1,2,3。n表示序列中包含的項數。根據所在位置找到此位置上的數據。
下四分位數Q1:該樣本中所有數值由小到大排列后第25%的數字。
中位數Q2:該樣本中所有數值由小到大排列后第50%的數字
上四分位數Q3:該樣本中所有數值由小到大排列后第75%的數字
四分位距IQR:IQR=Q3-Q1
上限:非異常范圍內的最大值,上限=Q3+1.5IQR
下限:非異常范圍內的最小值,下限=Q1-1.5IQR
3.Python代碼
def OutlierDetection_box(df,con,path):#con代表數據列的名稱,path代表文本保存的路徑# 計算下四分位數和上四分位Q1 = df.quantile(q=0.25)Q3 = df.quantile(q=0.75)Q2 = df.quantile(q=0.5)# 基于1.5倍的四分位差計算上下須對應的值low_whisker = Q1 - 1.5 * (Q3 - Q1)up_whisker = Q3 + 1.5 * (Q3 - Q1)# 尋找異常點outliers = df[(df > up_whisker) | (df < low_whisker)]#data1 = pd.DataFrame({'id': kk.index, '異常值': kk})#統計,stat_ll為箱型圖中數據分布情況(多個數據列合并最后會輸出一個sheet頁),f最后會輸出一個標識具體數據點的文本dataQ3=df[(df>Q2) & (df<=Q3)]countQ3=len(dataQ3)dataQ1 = df[(df < Q2) & (df >= Q1)]countQ1 = len(dataQ1)data_max = df[(df <= up_whisker) & (df > Q3)]count_max = len(data_max)data_min = df[(df >= low_whisker) & (df < Q1)]count_min = len(data_min)stat_ll=[con,countQ3,countQ1,count_max,count_min]with open(path+"/box_new.txt", "a",encoding='utf-8') as f:f.write("\n%s的箱型圖分布統計如下:"%con)f.write("\n箱線圖檢測到的異常值如下:")f.write(str(outliers.to_dict()))f.write("\n落入中位數到上四分位距有%d條,具體如下:"%countQ3)f.write(str(dataQ3.to_dict()))f.write("\n落入中位數到下四分位距有%d條,具體如下:" % countQ1)f.write(str(dataQ1.to_dict()))f.write("\n落入上四分位數到最大值有%d條,具體如下:" % count_max)f.write(str(data_max.to_dict()))f.write("\n落入下四分位數到最小值有%d條,具體如下:" % count_min)f.write(str(data_min.to_dict()))return outliers,stat_ll?2.正態分布
def OutlierDetection_std(df,con,path):# 計算均值u = df.mean()# 計算標準差std = df.std()# 計算P值res = kstest(df, 'norm', (u, std))[1]if res <= 0.05:#判斷是不是符合正態分布# 定義3σ法則識別異常值# 識別異常值error_low = df[np.abs(df - u) > 2 * std]error_high = df[np.abs(df - u) > 3 * std]# 剔除異常值,保留正常的數據#data_normal = df[np.abs(df - u) <= 3 * std]with open(path+"/std_outliers.txt", "a", encoding='utf-8') as f:f.write("\n%s符合正態分布:"%con)f.write("\n2sigma異常值如下:")f.write(str(error_low.to_dict()))f.write("\n3sigma異常值如下:")f.write(str(error_high.to_dict()))return u, std, error_low, error_highelse:logger.info('該數據不服從正態分布-----------')return None3.正態分布結合四分位距(網上一篇文章看到的,實際沒有使用)
def box_3Sigma(df,sigma):Q1 = df.quantile(q=0.25)Q3 = df.quantile(q=0.75)IQR = Q3 - Q1min = Q1 - 1.5 * IQRmax = Q3 + 1.5 * IQRratio = 0.3low = 3*sigma * ratio + min * (1 - ratio)hight = 3*sigma * ratio + max * (1 - ratio)總結
以上是生活随笔為你收集整理的Python:异常值检测箱型图(附:正态分布3σ)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python,OpenCV中的光学字符识
- 下一篇: TrOCR:基于Transformer的