Python数据分析-异常数据处理

448 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

本文为博主在处理异常数据的笔记与总结,如有理解不当之处,欢迎指正。

个人博客连接: JMX的个人博客

本篇文章主要是解决单变量数据集中的异常点分析,本代码中对异常数据的处理方式为删除,剔除异常数据,也可以适当修改,对异常数据进行自己需要的操作。

1. 四分位法

原理介绍: 首先计算出第一四分位数(Q1)、中位数(第二四分位数Q2)、第三四分位数(Q3)。 中位数也就是将一组数字按从小到大的顺序排序后,处于中间位置(也就是50%位置)的数字。 同理,第一四分位数、第三四分位数是按从小到大的顺序排序后,处于25%、75%的数字。 四分位法找出异常数据是利用:

IQR=Q3Q1IQR=Q3−Q1,那么 Q3+1.5(IQR)Q3+1.5(IQR)Q11.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计算公式为Zi=xiXstdZ_i=\frac {x_i-X}{std}

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定义为: MAD=medianxiXMAD=median{|x_i-X|}

medianmedian为取中位数,XX为数据的中位数

Mi=0.6475(xiX)MADM_i=\frac{0.6475(x_i-X)}{MAD}

取阈值为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做单变量数据集的异常点分析