【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中去除即可。
python
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的一些优秀的运算性质来解决问题。
- 在学习新知识的时候查询多手资料,不要盲信题目中给出的知识点讲解。