【Educoder数据挖掘实训】异常值检测-箱线图
开挖!
关于箱线图,核心理念就是找出上四分位数和下四分位数,定义二者的差为
I
Q
R
IQR
IQR。上下四分位数分别向上下扩展
1.5
I
Q
R
1.5IQR
1.5IQR定义为上界和下界,在此之外的数据被认为是异常数据。
这当然是合理的,关键在于四分位数如何求。
这是实训中给出的方法,这当然是错误的。
四分位数是没有办法仅通过一条公式算出来的,肯定要分类讨论。由于是除以四所以分为
0.25
,
0.5
,
0.75
,
0
0.25,0.5,0.75,0
0.25,0.5,0.75,0四种情况。
靠哪边近哪边占据更大权重才是合理的,比如
0.25
0.25
0.25的情况下就有
Q
i
=
0.75
⋅
x
[
i
(
l
+
1
)
/
/
4
]
+
0.25
⋅
x
[
i
(
l
+
1
)
/
/
4
+
1
]
Q_i=0.75\cdot x[i(l+1)//4]+0.25\cdot x[i(l+1)//4+1]
Qi=0.75⋅x[i(l+1)//4]+0.25⋅x[i(l+1)//4+1]。
其余三种情况同理。
但是分类讨论比较麻烦,我们可以借助quantile函数帮助我们直接求出上下四分位点。
求出分位点之后,我们理所当然知道了上限和下限。
此时我们可以借助
S
e
r
i
e
s
Series
Series数据类型的特殊运算性质我们求出异常值
b
o
o
l
bool
bool类型的
s
e
r
i
e
s
series
series,然后将他取反后在原
s
e
r
i
e
s
series
series中去除即可。
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
import numpy as np
data = pd.read_csv("src/death.csv", index_col='Unnamed: 0')
data = data.dropna(axis=1, thresh=data.shape[0] * 0.2)
data = data.dropna(axis=0, thresh=data.shape[1] * 0.2)
a = pd.isna(data).sum()
cols = [x for i, x in enumerate(a.index) if a[i] > 0]
mode_list = 'FIPS Admin2'
for i in cols:
if mode_list.find(i) != -1:
data[i] = data[i].fillna(data[i].mode().iloc[0])
else:
data[i] = data[i].fillna(data.mean()[i])
cols = '2008/10/20,2008/11/20,2008/12/20'.split(',')
x = data[cols]
########## Begin ##########
Q1 = x.quantile(0.25)
Q3 = x.quantile(0.75)
IQR = Q3 - Q1
lower_limit = Q1 - 1.5 * IQR
upper_limit = Q3 + 1.5 * IQR
outliers_index = (x < lower_limit) | (x > upper_limit)
x_c1 = x[~outliers_index]
print(outliers_index.sum())
########## End ##########
x_c1.boxplot()
plt.savefig(r'src/step1/ans_img')
plt.show()
解决问题的关键在于两点:
- 看预计输出知道最后需要输出的数据类型是一个 s e r i e s series series,后我们通过查询 s e r i e s series series的一些优秀的运算性质来解决问题。
- 在学习新知识的时候查询多手资料,不要盲信题目中给出的知识点讲解。