首页 > 编程知识 正文

python数据异常值的处理,异常值 python

时间:2023-05-06 17:07:03 阅读:195434 作者:3232

异常值是指样本中的个别值明显偏离其余的观测值。异常值的存在会对数据分析、建模产生干扰,因此需要对数据集进行异常值检测并进行异常值删除或修正,以便后续更好地进行数据分析和挖掘。对于异常值检测,有描述性统计、3σ原则方法、箱线图、基于聚类的方法等,而3σ原则是最常使用的异常值检测方法之一。在3σ原则下,一般认为数据的取值99.7%的概率集中在(μ-3σ,μ+3σ)区间内(μ为平均值,σ为标准差),超出这个范围的可能性仅占0.3%,属于极个别的小概率事件,因此将超出(μ-3σ,μ+3σ)范围的值认为是异常值。3σ原则要求数据服从正态或近似正态分布,且样本数据大于10。若数据不服从正态分布,也可以用远离平均值的多少倍标准差来描述。现利用Python实现基于3σ原则的异常值检测,并对从网络上查询的中国1952年-2018年中国GDP(亿元)、GDP指数((上年=100)) 人均GDP(元)、GDP增长率(%)、第二产业增加值(亿元) 、第三产业增加值(亿元)等24个指标数据进行异常值检测。

#基于3sigma的异常值检测#-*- coding: utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as plt #导入绘图库##3sigma原则def threesigma(data,n): ''' data:表示时间序列,包括时间和数值两列; n:表示几倍的标准差 ''' data_x = data.ix[:,0].tolist() ##获取时间序列的时间 #print (data_x) #print ("**********",j) mintime=data_x[0] ##获取时间序列的起始年份 maxtime=data_x[-1] ##获取时间序列的结束年份 data_y = data.ix[:,1].tolist() ##获取时间序列数值 ymean = np.mean(data_y) ##求时间序列平均值 ystd = np.std(data_y) ##求时间序列标准差 down = ymean - n * ystd ##计算下界 up = ymean + n * ystd ##计算上界 outlier = [] #将异常值保存 outlier_x = [] for i in range(0, len(data_y)): if (data_y[i] < down)|(data_y[i] > up): outlier.append(data_y[i]) outlier_x.append(data_x[i]) else: continue return mintime,maxtime,outlier,outlier_x#设置列表,用于记录结果indicator=[] ##指标flag=[] ##是否为异常值outlier_data=[] ##异常值outlier_time=[] ##出现异常值的对应时间max_time=[] ##时间序列的开始时间min_time=[] ##时间序列的结束时间time_flag=[] ##异常值是否为起始时间#读取数据data = pd.read_csv( 'data.csv', index_col = False,encoding='gb18030') #读取数据#print(data.head())col_name=data.columns.tolist()#print (data.columns.tolist())#设置参数n = 3 # n*sigmaprint ("******************:n=",n)##依次检测每一个指标for j in col_name[1:]: indicator.append(j) temp_data=data.ix[:,['时间',j]] #print ("删除空值前",len(temp_data)) temp_data=temp_data.dropna() #删除空值 #print("删除空值后",len(temp_data)) temp_data=temp_data.sort_values(by = ['时间'],axis = 0,ascending = True) #按时间排序 #print (temp_data) mintime,maxtime,outlier,outlier_x=threesigma(temp_data,n) #调用3sigma函数 min_time.append(mintime) ##获取时间序列的起始年份 max_time.append(maxtime) ##获取时间序列的结束年份 outlier_data.append(outlier) outlier_time.append(outlier_x) if (maxtime in outlier_x) or (mintime in outlier_x): time_flag.append('异常值为起始端') #print (time_flag) else: time_flag.append("") if len(outlier)>0: flag.append('异常') print("***************************") print ("异常指标:",j) print('n异常数据如下:',outlier,outlier_x) ##画出存在异常值的时间序列的折线图,异常值处特殊标注 plt.figure(figsize=(12,5)) plt.plot(temp_data.ix[:,0], temp_data.ix[:,1]) plt.plot(outlier_x, outlier, 'ro') for j in range(len(outlier)): plt.annotate(outlier[j], xy=(outlier_x[j], outlier[j]), xytext=(outlier_x[j],outlier[j])) plt.show() else: flag.append('正常') result=pd.DataFrame()result['指标']=indicatorresult['开始时间']=min_timeresult['结束时间']=max_timeresult['是否异常']=flagresult['异常数值']=outlier_dataresult['异常时间']=outlier_timeresult['异常值所处时间标识']=time_flagresult


对于抛出来的异常值要重点关注,并且结合实际的业务情况来判断数据是否真的存在异常,以及何种原因导致的异常,进而确定异常值的处理方式。

GDP指数(上年=100):1961年我国刚刚经过三年自然灾害,查询多方面资料证实数据没有问题,不作处理。
第三产业占GDP比重(%):查询多方面资料证实数据确实存在问题,进行修正。
第三产业增加值(亿元):异常值出现在时间序列的起始端,通过折线图和多方面资料证实数据没有问题,不作处理。

附数据和源程序。链接:https://pan.baidu.com/s/1RLC6769nJLKUG3woWsv17w 提取码:rmjc

ps:初衷是通过撰写博文记录自己所学所用,实现知识的梳理与积累;将其分享,希望能够帮到面临同样困惑的小伙伴儿。如发现博文中存在问题,欢迎随时交流~~

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。