Python數據分析:異常值檢驗的兩種方法 -- Z 分數 & 上下分位點(放入自寫庫,一行代碼快速實現)

在這裏插入圖片描述

引言

  數據預處理時,異常值的存在可能對最終建立的模型的精度和泛化能力有較大的影響。檢測異常值的方式有很多,最基本的兩種方法爲 z 分數法和上下截斷點法。

對 z 分數法還存在些許疑慮的可查看如下博文

統計學: Z 分數 & 正態分佈 (附 Python 實現代碼) --Z 檢驗先修; Z 分數與正態分佈兩者關係; Z 分數與百分位數的異同;面試要點(以心理學實驗爲舟)

  本文針對這兩種方法,構造自寫庫,最終實現函數的快捷調用,在很大程度上提高了數據預處理的效率。


效果展示(Jupyter notebook)

在這裏插入圖片描述
一行代碼快速繪圖查看房價分佈情況
在這裏插入圖片描述
如何一步到位的畫出複雜精美的圖片可以參考這篇博文

Python 數據可視化:seaborn displot 正態分佈曲線擬合圖代碼註釋超詳解(放入自寫庫,一行代碼搞定複雜細節繪圖)

以某列作爲基準檢測時,返回的異常值是包含該列在呢的整行完整的數據。
在這裏插入圖片描述
在這裏插入圖片描述



完整代碼

  這個函數是筆者自己編寫的,功能非常簡單,難度中下,但實現的效果還是挺好用的,其實還有一些值得優化的地方,歡迎在評論出指出,一起交流。

# 基礎庫
import numpy as np
import pandas as pd

# 提高輸出效率庫
from IPython.core.interactiveshell import InteractiveShell # 實現 notebook 的多行輸出
InteractiveShell.ast_node_interactivity = 'all' #默認爲'last'

# ------------------------- 異常值檢驗(常規方法) ------------------------
# ================ 異常值檢驗函數:iqr & z分數 兩種方法 =========================
def outlier_test(data, column, method=None, z=2):
    """ 以某列爲依據,使用 上下截斷點法 檢測異常值(索引) """
    """ 
    full_data: 完整數據
    column: full_data 中的指定行,格式 'x' 帶引號
    return 可選; outlier: 異常值數據框 
    upper: 上截斷點;  lower: 下截斷點
    method:檢驗異常值的方法(可選, 默認的 None 爲上下截斷點法),
            選 Z 方法時,Z 默認爲 2
    """
    # ================== 上下截斷點法檢驗異常值 ==============================
    if method == None:
        print(f'以 {column} 列爲依據,使用 上下截斷點法(iqr) 檢測異常值...')
        print('=' * 70)
        # 四分位點;這裏調用函數會存在異常
        column_iqr = np.quantile(data[column], 0.75) - np.quantile(data[column], 0.25)
        # 1,3 分位數
        (q1, q3) = np.quantile(data[column], 0.25), np.quantile(data[column], 0.75)
        # 計算上下截斷點
        upper, lower = (q3 + 1.5 * column_iqr), (q1 - 1.5 * column_iqr)
        # 異常值所在行索引: 大於上截斷點 & 小於下截斷點
        outlier_index = []  # argwhere 返回索引
        outlier_upper = np.argwhere(data[column] > upper)
        outlier_lower = np.argwhere(data[column] < lower)
        outlier_index.append(outlier_upper)
        outlier_index.append(outlier_lower)
        # 寫進數據框
        outlier = pd.DataFrame()
        outlier = outlier.append(data[data[column] >= upper])
        outlier = outlier.append(data[data[column] <= lower])
        print(f'第一分位數: {q1}, 第三分位數:{q3}, 四分位極差:{column_iqr}')
        print(f"上截斷點:{upper}, 下截斷點:{lower}")
        return outlier, upper, lower
    # ===================== Z 分數檢驗異常值 ==========================
    if method == 'z':
        """ 以某列爲依據,傳入數據與希望分段的 z 分數點,返回異常值索引與所在數據框 """
        """ 
        params
        data: 完整數據
        column: 指定的檢測列
        z: Z分位數, 默認爲2,根據 z分數-正態曲線表,可知取左右兩端的 2%,
           根據您 z 分數的正負設置。也可以任意更改,知道任意頂端百分比的數據集合
        """
        print(f'以 {column} 列爲依據,使用 Z 分數法,z 分位數取 {z} 來檢測異常值...')
        print('=' * 70)
        # 計算兩個 Z 分數的數值點
        mean, std = np.mean(data[column]), np.std(data[column])
        upper, lower = (mean + z * std), (mean - z * std)
        print(f"取 {z} 個 Z分數:大於 {upper} 或小於 {lower} 的即可被視爲異常值。")
        print('=' * 70)

        # 異常值所在行索引列:數據大於你設置的x個z分數點的數據 + 小於x個z分數點的數據
        outlier_index = []
        outlier_upper = np.argwhere(data[column] >= upper)
        outlier_lower = np.argwhere(data[column] <= lower)
        outlier_index.append(outlier_upper)
        outlier_index.append(outlier_lower)
        # 寫進數據框
        outlier = pd.DataFrame()
        outlier = outlier.append(data[data[column] >= upper])
        outlier = outlier.append(data[data[column] <= lower])
        
        return outlier, upper, lower

值得注意的是, 如果確定了是用 z-score 或者 iqr 法,注意只是處理一次即可。只要是再次檢測,就又會有 “ 新的 ” 異常值出現,因爲 z-score/iqr 的計算公式會根據第一次處理後的新的樣本集來弄。



後記

  數據分析,商業實踐,數據可視化,網絡爬蟲,統計學,Excel,Word, 社會心理學,認知心理學,行爲科學,民族意志學 各種專欄後續瘋狂補充

  歡迎評論與私信交流!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章