1. 程式人生 > >一種異常值檢測方法、原理 (基於箱線圖)

一種異常值檢測方法、原理 (基於箱線圖)

先介紹使用到的方法原理,也就是一種異常檢測的方法。  首先要先了解箱線圖。

箱線圖

箱線圖(Boxplot)也稱箱須圖(Box-whisker Plot),是利用資料中的五個統計量:最小值、第一四分位數、中位數、第三四分位數與最大值來描述資料的一種方法,它也可以粗略地看出資料是否具有有對稱性,分佈的分散程度等資訊,特別可以用於對幾個樣本的比較。 ——MBAlib 箱線圖

先看一下什麼是箱線圖,下面這個是常見的箱線圖樣子。

箱線圖1

具體含義如下,首先計算出第一四分位數(Q1)、中位數、第三四分位數(Q3)。  中位數我們都知道,就是將一組數字按從小到大的順序排序後,處於中間位置(也就是50%位置)的數字。  同理,第一四分位數、第三四分位數是按從小到大的順序排序後,處於25%、75%的數字。

令 IQR=Q3−Q1IQR=Q3−Q1 ,那麼 Q3+1.5(IQR)Q3+1.5(IQR) 和 Q1−1.5(IQR)Q1−1.5(IQR) 之間的值就是可接受範圍內的數值,這兩個值之外的數認為是異常值。

在Q3+1.5IQR(四分位距)和Q1-1.5IQR處畫兩條與中位線一樣的線段,這兩條線段為異常值截斷點,稱其為內限;在Q3+3IQR和Q1-3IQR處畫兩條線段,稱其為外限。 處於內限以外位置的點表示的資料都是異常值,其中在內限與外限之間的異常值為溫和的異常值(mild outliers),在外限以外的為極端的異常值(li)的異常值extreme outliers。這種異常值的檢測方法叫做Tukey’s method

從矩形盒兩端邊向外各畫一條線段直到不是異常值的最遠點 表示該批資料正常值的分佈區間點,示該批資料正常值的分佈區間。  一般用“〇”標出溫和的異常值,用“*”標出極端的異常值。

箱線圖含義

python 程式碼分享

通過上面對箱線圖的介紹,相信同時也清楚了異常值檢測的方法。  假設我們現在已經有了一份pandas.DataFrame讀取後的資料df,其中需要進行檢測的列儲存在features列表中,每個樣本能忍受的最大異常值數量為n。

# Outlier detection 
import pandas as pd
import numpy as np
from collections import Counter

def detect_outliers(df,n,features):

    outlier_indices = []

    # iterate over features(columns)
    for col in features:
        # 1st quartile (25%)
        Q1 = np.percentile(df[col], 25)
        # 3rd quartile (75%)
        Q3 = np.percentile(df[col],75)
        # Interquartile range (IQR)
        IQR = Q3 - Q1

        # outlier step
        outlier_step = 1.5 * IQR

        # Determine a list of indices of outliers for feature col
        outlier_list_col = df[(df[col] < Q1 - outlier_step) | (df[col] > Q3 + outlier_step )].index

        # append the found outlier indices for col to the list of outlier indices 
        outlier_indices.extend(outlier_list_col)

    # select observations containing more than 2 outliers
    outlier_indices = Counter(outlier_indices)        
    multiple_outliers = list( k for k, v in outlier_indices.items() if v > n )

    return multiple_outliers   
# detect outliers from "Col1","Col2","Col3","Col4"
df = pd.read_csv("data.csv")
Outliers_to_drop = detect_outliers(df,2,["Col1","Col2","Col3","Col4"])
# Drop outliers
df = df.drop(Outliers_to_drop, axis = 0).reset_index(drop=True)