本文为博主在处理异常数据的笔记与总结,如有理解不当之处,欢迎指正。
个人博客连接: JMX的个人博客
本篇文章主要是解决单变量数据集中的异常点分析,本代码中对异常数据的处理方式为删除,剔除异常数据,也可以适当修改,对异常数据进行自己需要的操作。
1. 四分位法
原理介绍:
首先计算出第一四分位数(Q1)、中位数(第二四分位数Q2)、第三四分位数(Q3)。
中位数也就是将一组数字按从小到大的顺序排序后,处于中间位置(也就是50%位置)的数字。
同理,第一四分位数、第三四分位数是按从小到大的顺序排序后,处于25%、75%的数字。
四分位法找出异常数据是利用:
令
I
Q
R
=
Q
3
−
Q
1
IQR=Q3−Q1
IQR=Q3−Q1,那么
Q
3
+
1.5
(
I
Q
R
)
Q3+1.5(IQR)
Q3+1.5(IQR) 和
Q
1
−
1.5
(
I
Q
R
)
Q1−1.5(IQR)
Q1−1.5(IQR)之间的值就是可接受范围内的数值,这两个值之外的数认为是异常值,该原理类似于正态分布中异常数据的检测,只是将阈值变成了由四分位点求得。
def detect_outliers_4div(df):
outlier_indices = []
raw = df
try:
# 1st quartile (25%)
Q1 = np.percentile(df, 25)
# 3rd quartile (75%)
Q3 = np.percentile(df, 75)
# Interquartile range (IQR)
IQR = Q3 - Q1
# outlier step
outlier_step = 1.5 * IQR
for nu in df:
if (nu < Q1 - outlier_step) | (nu > Q3 + outlier_step):
df.remove(nu)
except:
return raw
return df
2. 基于标准差的检测方法
假设数据是正态分布的,由概率论中的知识我们可以知道:
- 95.449974%的数据在平均数左右两个标准差范围内
- 99.730020%的数据在平均数左右三个标准差范围内
- 99.993666%的数据在平均数左右四个标准差范围内
以95%作为示例阈值,来剔除异常点。
def detect_outliers_std(df,threshold=0.95):
outlier_indices = []
for nu in df:
if nu > np.quantile(df,threshold):
df.remove(nu)
return df
3. 基于ZSCORE检测方法
ZSCORE计算公式为 Z i = x i − X s t d Z_i=\frac {x_i-X}{std} Zi=stdxi−X
std为数据标准差,X为数据均值
我们取阈值为3.5,代码如下:
def detect_outliers_zscore(df,threshold=3.5):
outlier_indices = []
for nu in df:
zscore = (nu - np.mean(df))/np.std(df)
if abs(zscore) > threshold:
df.remove(nu)
return df
4. 基于MAD检测方法
该方法为对ZSCORE方法的增强,MAD定义为:
M
A
D
=
m
e
d
i
a
n
∣
x
i
−
X
∣
MAD=median{|x_i-X|}
MAD=median∣xi−X∣
m e d i a n median median为取中位数, X X X为数据的中位数
M i = 0.6475 ( x i − X ) M A D M_i=\frac{0.6475(x_i-X)}{MAD} Mi=MAD0.6475(xi−X)
取阈值为3.5,代码如下:
def detect_outliers_mad(df,threshold=3.5):
outlier_indices = []
MAD = np.median(abs(df - np.median(df)))
for nu in df:
zscore = abs((nu - np.median(df))*0.6475/MAD)
if zscore > threshold:
df.remove(nu)
return df
完整代码如下:
#_*_coding:utf-8_*_
# author : jmx
# create : 19-9-17 上午10:31
# filename : test.py
# IDE : PyCharm
import numpy as np
def detect_outliers_4div(df):
outlier_indices = []
raw = df
try:
# 1st quartile (25%)
Q1 = np.percentile(df, 25)
# 3rd quartile (75%)
Q3 = np.percentile(df, 75)
# Interquartile range (IQR)
IQR = Q3 - Q1
# outlier step
outlier_step = 1.5 * IQR
for nu in df:
if (nu < Q1 - outlier_step) | (nu > Q3 + outlier_step):
df.remove(nu)
except:
return raw
return df
def detect_outliers_std(df,threshold=0.95):
outlier_indices = []
for nu in df:
if nu > np.quantile(df,threshold):
df.remove(nu)
return df
def detect_outliers_zscore(df,threshold=3.5):
outlier_indices = []
for nu in df:
zscore = (nu - np.mean(df))/np.std(df)
if abs(zscore) > threshold:
df.remove(nu)
return df
def detect_outliers_mad(df,threshold=3.5):
outlier_indices = []
MAD = np.median(abs(df - np.median(df)))
for nu in df:
zscore = abs((nu - np.median(df))*0.6475/MAD)
if zscore > threshold:
df.remove(nu)
return df
df = [-0.2296411544084549,-1.404792070388794,-0.0,-1.3356698751449585,-4.174769878387451,
84.90332174301147,-0.0,-0.0]
clean = detect_outliers_std(df)
print(clean)
参考文章:用Python做单变量数据集的异常点分析