一辐啄、異常值
1.異常值是指樣本中的個(gè)別值,其數(shù)值明顯偏離其余的觀測(cè)值运嗜。異常值也稱(chēng)離群點(diǎn),異常值的分析也稱(chēng)為離群點(diǎn)的分析
-
2.異常值的處理悯舟,先是辨別出哪些是異常值担租,再根據(jù)實(shí)際情況選擇如何處理異常值。
- 偽異常抵怎,比如由于特定業(yè)務(wù)運(yùn)營(yíng)而產(chǎn)生的奋救;
- 真異常岭参,并非業(yè)務(wù)運(yùn)營(yíng)而產(chǎn)生的,是客觀反映數(shù)據(jù)本身存在異常的分布尝艘。
-
3.異常值分析
- 3σ原則
- 箱型圖
-
4.異常值的處理方法
- 剔除異常值
- 視為缺失值NaN演侯,填補(bǔ)處理
- 不處理
二、異常值分析及處理
1.方法1 → 3σ原則
3σ原則是指若數(shù)據(jù)服從正態(tài)分布背亥,異常值被定義為一組測(cè)定值與其平均值的差的絕對(duì)值超過(guò)3倍標(biāo)準(zhǔn)差值 → p(|x - μ| > 3σ) ≤ 0.003
秒际!但使用3σ原則需要先判斷數(shù)據(jù)是否服從正態(tài)分布,服從正態(tài)分布才能使用該原則判斷異常值
第一步:正態(tài)性檢驗(yàn)
正態(tài)性檢驗(yàn)是指利用觀測(cè)數(shù)據(jù)判斷總體是否服從正態(tài)分布的檢驗(yàn)稱(chēng)為正態(tài)性檢驗(yàn)狡汉,它是統(tǒng)計(jì)判決中重要的一種特殊的擬合優(yōu)度假設(shè)檢驗(yàn)
→ 正態(tài)性檢驗(yàn)方法:KS檢驗(yàn)
→KS檢驗(yàn)理論簡(jiǎn)介:
- KS(Kolmogorov-Smirnov)檢驗(yàn)用于檢驗(yàn)數(shù)據(jù)是否符合某種分布娄徊,是比較一個(gè)頻率分布f(x)與理論分布g(x)或者兩個(gè)觀測(cè)值分布的檢驗(yàn)方法。
- 其原假設(shè)H0:兩個(gè)數(shù)據(jù)分布一致或者數(shù)據(jù)符合理論分布盾戴。D=max| f(x)- g(x)|寄锐,當(dāng)實(shí)際觀測(cè)值D>D(n,α)則拒絕H0,否則則接受H0假設(shè)尖啡。KS檢驗(yàn)與t-檢驗(yàn)之類(lèi)的其他方法不同橄仆,KS檢驗(yàn)不需要知道數(shù)據(jù)的分布情況,可以算是一種非參數(shù)檢驗(yàn)方法衅斩。
- 當(dāng)然這樣方便的代價(jià)就是當(dāng)檢驗(yàn)的數(shù)據(jù)分布符合特定的分布時(shí)盆顾,KS檢驗(yàn)的靈敏度沒(méi)有相應(yīng)的檢驗(yàn)來(lái)的高。在樣本量比較小的時(shí)候矛渴,KS檢驗(yàn)在為非參數(shù)檢驗(yàn)在分析兩組數(shù)據(jù)之間是否不同時(shí)椎扬,是相當(dāng)常用。
- 雖然KS檢驗(yàn)的定義中說(shuō)檢驗(yàn)的數(shù)據(jù)必須是連續(xù)的具温,若在非連續(xù)數(shù)據(jù)上用KS檢驗(yàn)檢驗(yàn)的顯著性回下降蚕涤,想要獲得準(zhǔn)確值就需要用其他檢驗(yàn),比如chi-square goodness-to-fit 但在實(shí)際操作中铣猩,如果離散分布的數(shù)據(jù)夠多的話(huà)揖铜,用KS檢驗(yàn)的顯著性不會(huì)有太大影響,可以比較放心使用达皿。
→ KS檢驗(yàn)的參數(shù)解釋?zhuān)?/strong>
- KS檢驗(yàn)會(huì)返回兩個(gè)值天吓,D值和p值。
- D值:表示兩個(gè)分布之間最大距離峦椰,即系D值越小龄寞,表示兩個(gè)分布的差距越小,分布也就越一致汤功。
- p值:表示假設(shè)檢驗(yàn)中的p值物邑,因?yàn)樵僭O(shè)為“待檢驗(yàn)的兩個(gè)數(shù)據(jù)的分布一致”,即系若p值>0.05(p值的設(shè)定取決于實(shí)際要求),那么就不能拒絕原假設(shè)色解,即系“待檢驗(yàn)的兩個(gè)數(shù)據(jù)分布一致”這個(gè)假設(shè)成立茂嗓。
# 設(shè)置cell多行輸出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默認(rèn)為'last'
# 導(dǎo)入相關(guān)庫(kù)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
os.chdir(r'E:\python_learn\train')
# 讀取數(shù)據(jù)
file_name = 'data_abnormal.csv'
data = pd.read_csv(file_name,usecols=['key1','key2','key3'])
print(data.head())
key1 key2 key3
0 171.478895 31.816106 -235.872855
1 38.145928 -44.222959 -45.868820
2 -14.594276 7.455609 -39.576063
3 118.362921 15.007191 83.177483
4 -5.589237 114.340285 135.983500
# 直接用算法做KS檢驗(yàn)
from scipy import stats
# 創(chuàng)建函數(shù)
def f(x):
return stats.kstest(x,'norm',(x.mean(),x.std()))
# .kstest方法:KS檢驗(yàn),參數(shù)分別是:待檢驗(yàn)的數(shù)據(jù)科阎,檢驗(yàn)方法(這里設(shè)置成norm正態(tài)分布)述吸,均值與標(biāo)準(zhǔn)差
data_stats = data.apply(f) # 將算法直接映射到每一列
data_stats.values
# 結(jié)果返回兩個(gè)值:statistic → D值,pvalue → P值
# p值大于0.05锣笨,為正態(tài)分布
array([KstestResult(statistic=0.009734859311949784, pvalue=0.7305177443558707),
KstestResult(statistic=0.008796876410950949, pvalue=0.8338347831965152),
KstestResult(statistic=0.013374626202709239, pvalue=0.3327578473536996)],
dtype=object)
從所返回的D值和p值得出蝌矛,數(shù)據(jù)集每列數(shù)據(jù)都符合正態(tài)分布的規(guī)律,因此可以使用3σ進(jìn)行異常值檢測(cè)票唆。
第二步:3σ檢測(cè)異常值和異常值處理
公式: |x - μ| >3σ為異常值朴读,也就是說(shuō)一組測(cè)定值與其平均值的差的絕對(duì)值超過(guò)3倍標(biāo)準(zhǔn)差值即為異常值
# 數(shù)據(jù)缺失值查看
print(data.head())
data.isna().sum()
data.isna().sum().sum() # → 不存在缺失值
key1 key2 key3
0 171.478895 31.816106 -235.872855
1 38.145928 -44.222959 -45.868820
2 -14.594276 7.455609 -39.576063
3 118.362921 15.007191 83.177483
4 -5.589237 114.340285 135.983500
key1 0
key2 0
key3 0
dtype: int64
0
# 篩出異常值
df = data.copy() # 復(fù)制一份數(shù)據(jù)
lst = []
cols = df.columns
for col in cols:
df_col = df[col]
err = df_col[np.abs(df_col-df_col.mean())>3*df_col.std()] # 篩出異常數(shù)據(jù)
lst.append(err)
err_data = pd.concat(lst)
print('一共檢測(cè)到異常值共:%i'%len(err_data),'\n')
print('異常值展示前10條:\n',err_data.head(10))
一共檢測(cè)到異常值共:43
異常值展示前10條:
197 318.319213
1319 331.880033
2074 -416.500736
2109 300.174181
2922 -488.395881
3182 360.454103
3793 324.765684
3863 335.669291
4096 -307.131874
4272 -310.307727
dtype: float64
# 將異常值替換為NaN,并插補(bǔ)補(bǔ)全
normal = df[np.abs(df-df.mean())<3*df.std()] # 異常值是|x - μ| >3σ走趋,反之小于3σ的值為正常
# 返回一個(gè)已用NaN替換掉異常值的DataFrame
normal.isna().sum() # 查看是否有空值 → 存在缺失值衅金,表示已將異常值替換為NaN
normal.isna().sum().sum()
df_clean = normal.fillna(normal.median()) # 使用中位數(shù)插補(bǔ)
df_clean.isna().sum()
df_clean.isna().sum().sum() # 檢查空值是否已處理
key1 11
key2 11
key3 21
dtype: int64
43
key1 0
key2 0
key3 0
dtype: int64
0
以上就是3σ原則檢測(cè)異常值的操作過(guò)程
2.方法2 → 箱形圖
箱形圖(Box-plot)又稱(chēng)為盒須圖、盒式圖或箱線(xiàn)圖簿煌,是一種用作顯示一組數(shù)據(jù)分散情況資料的統(tǒng)計(jì)圖氮唯。
(1)箱形圖的六個(gè)數(shù)據(jù)節(jié)點(diǎn):
- 上四分位數(shù)(Q1)
- 中位數(shù)(Q2)
- 下四分位數(shù)(Q3)
- 四分位距(IQR):IQR = Q3-Q1
- 上限(最大值區(qū)域):Q3+1.5IQR
- 下限(最小值區(qū)域):Q1-1.5IQR
- 異常值,被定義為小于Q1-1.5IQR或大于Q3+1.5IQR的值
(2)箱形圖的作用:
-
① 識(shí)別數(shù)據(jù)的異常值
- 箱型圖的異常值被定義為小于Q1-1.5IQR或大于Q3+1.5IQR的值
- 3σ原則需要以數(shù)據(jù)服從正態(tài)分布為前提姨伟,但實(shí)際數(shù)據(jù)往往不能?chē)?yán)格服從正態(tài)分布惩琉,且其判斷異常值的標(biāo)準(zhǔn)以計(jì)算數(shù)據(jù)的均值和標(biāo)準(zhǔn)差為基礎(chǔ),而均值和標(biāo)準(zhǔn)差耐抗性較小夺荒,異常值本身對(duì)他們影響就較大瞒渠,因此產(chǎn)生的異常值個(gè)數(shù)不會(huì)多于總數(shù)的0.7%。
- 但箱型圖與值對(duì)比其優(yōu)勢(shì)是技扼,不需事先假定數(shù)據(jù)服從特定的分布伍玖,沒(méi)有對(duì)數(shù)據(jù)做限制要求,真實(shí)直觀低呈現(xiàn)數(shù)據(jù)本來(lái)面貌剿吻,且箱型圖以四分位數(shù)和四分位距作為基礎(chǔ)窍箍,具有一定耐抗性,箱形圖識(shí)別異常值的結(jié)果比較客觀丽旅。
-
② 易于發(fā)現(xiàn)數(shù)據(jù)的偏態(tài)和尾重
- 標(biāo)準(zhǔn)正態(tài)分布的樣本椰棘,只有0.7%的值是異常值,中位數(shù)位于上下四分位數(shù)的中央榄笙,箱型圖的方盒關(guān)于中位線(xiàn)對(duì)稱(chēng)邪狞。
- 異常值集中在較大值一側(cè),則分布呈現(xiàn)右偏態(tài)茅撞;帆卓;異常值集中在較小值一側(cè),則分布呈現(xiàn)左偏態(tài)鳞疲。盡管不能給出偏態(tài)和尾重程度的精確度量,但可作為粗略估計(jì)的依據(jù)蠕蚜。
-
③ 能用于數(shù)據(jù)性探索分析尚洽,分析數(shù)據(jù)的形狀
- 多組數(shù)據(jù)箱型圖并排對(duì)比靶累,能一目了然的查看中位數(shù),尾長(zhǎng)挣柬,異常值潮酒,分布區(qū)間等信息。
print(data.head()) # 原始數(shù)據(jù)展示
# 查看缺失值
data.isna().sum()
data.isna().sum().sum() # → 不存在缺失
key1 key2 key3
0 171.478895 31.816106 -235.872855
1 38.145928 -44.222959 -45.868820
2 -14.594276 7.455609 -39.576063
3 118.362921 15.007191 83.177483
4 -5.589237 114.340285 135.983500
key1 0
key2 0
key3 0
dtype: int64
0
# 箱型圖查看數(shù)據(jù)
color = dict(boxes='DarkGreen', whiskers='DarkOrange', medians='DarkBlue', caps='Gray') # 顏色設(shè)置
box=df2.plot.box(figsize=(12,8),return_type='dict',color=color)
plt.title('異常值檢測(cè)-箱型圖',fontsize=14,pad=12)
從箱型圖反映的情況可知急黎,每列數(shù)據(jù)都存在異常值的情況。
# 篩出異常值
df2 = data.copy() # 復(fù)制一份數(shù)據(jù)
lst = []
cols = df2.columns
for col in cols:
df2_col = df2[col]
q1 = df2_col.quantile(0.25)
q3 = df2_col.quantile(0.75)
iqr = q3-q1
ma = q3+iqr*1.5
mi = q1-iqr*1.5
error = df2_col[(df2_col>ma) | (df2_col<mi)] # 篩出異常
lst.append(error)
err_data = pd.concat(lst)
print('一共檢測(cè)到異常值共:%i'%len(err_data),'\n')
print('異常值展示前10條:\n',err_data.head(10))
一共檢測(cè)到異常值共:130
異常值展示前10條:
85 -296.923702
197 318.319213
344 -268.979898
461 266.571340
609 -294.773187
615 -278.354103
819 293.908994
860 -275.333416
946 -269.933060
1232 278.143495
dtype: float64
# 處理異常值 → 替換為NaN侧到,并以插值方法處理
Q1 = df2.quantile(0.25)
Q3 = df2.quantile(0.75)
IQR = Q3-Q1
Max = Q3+IQR*1.5
Min = Q1-IQR*1.5
data_nor = df2[(df2 >= Min) & (df2 <= Max)] # 將正常的數(shù)據(jù)按數(shù)據(jù)框形式篩選出來(lái)勃教,返回一個(gè)已用NaN替換掉異常值的DataFrame
data_nor.isna().sum()
data_nor.isna().sum().sum()
# 插值處理NaN
data_clean = data_nor.fillna(data_nor.median())
data_clean.isna().sum() # 確認(rèn)缺失值已處理
key1 45
key2 32
key3 53
dtype: int64
130
key1 0
key2 0
key3 0
dtype: int64
以上就是箱型圖檢測(cè)異常值的操作過(guò)程*