欢迎来到Introzo百科
Introzo百科
当前位置:网站首页 > 技术 > Python:异常值检测箱线图(附件:正态分布3σ)

Python:异常值检测箱线图(附件:正态分布3σ)

日期:2023-09-30 19:47

异常值检测的方法有很多种。通过数据分布模式查找异常值和算法模型(聚类、随机森林等)。下面是我所做的记录一下工作中初步数据探索中用到的箱线图检测和正态分布检测。这两者都用于根据数据分布识别异常值。它们没有与业务层面结合起来。在做初步探索的时候还是高效、适用的。由于正态分布3σ的异常值检测要求数据符合正态分布,而现实中大部分数据都是杂乱的,所以主要采用箱线图检测。

1。箱线图的优点

(1)准确、稳定地刻画数据的离散分布,不服从特定的分布形式

箱线图的绘制依赖于实际数据。 无需提前假设数据服从特定的分布形式。它不对数据施加任何限制性要求。它只是真实、直观地代表数据形态的本来面目;

(2) 异常值不会影响四分位数的确定

箱线图中异常值的判断标准基于四分位数四分位数范围。四分位数具有一定的抵抗力,最高可达25%数据可以变得任意远而不会对四分位数产生很大的干扰,因此异常值不能对这个标准产生影响,箱线图的结果可以识别异常值更客观。

2。箱线图及符号解释

(图片来源于网络)

Qi 的位置为 =i (n+1)/4,其中 i=1, 2, 3。n 表示序列中包含的项目数。根据位置查找此位置的数据。

下四分位数Q1:样本中所有值从小到大排列的25%个数。

中位数Q2:样本中所有值从小到大排列的50%个数

上四分位数Q3:样本中所有值从小到大排列的第75个百分位

四分位数范围IQR:IQR=Q3-Q1

上限:非异常范围内的最大值,上限=Q3+1.5IQR

下限:非异常范围内的最小值,下限=Q1-1.5IQR

3.Python代码

def OutlierDetection_box(df,con,path): #con代表数据列的名称,path代表文本保存的路径 # 计算下四分位数和上四分位数 Q1 = df.quantile(q=0.25) Q3 = df.quantile(q=0.75)Q2 = df.quantile(q=0.5)#根据1.5倍四分位差计算上下须线对应的值 low_whisker = Q1 - 1.5 * (Q3 - Q1 )up_whisker = Q3 + 1.5 * (Q3 - Q1)# 查找异常值 = df[(df > up_whisker) | (df < low_whisker)]#data1 = pd.DataFrame({'id': kk.index, '异常值': kk})#统计,stat_ll为箱型图中数据分布情况(多个数据列合并最后会输出一个sheet页),f最后会输出一个标识具体数据点的文本dataQ3=df[(df>Q2) & (df<=Q3)]countQ3=len(dataQ3)dataQ1 = df[(df < Q2) & (df >= Q1)]countQ1 = len(dataQ1)data_max = df[(df <= up_whisker) & (df > Q3)]count_max = len(data_max)data_min = df[(df >= low_whisker) ) & (df < Q1)]count_min = len(data_min)stat_ll=[con,countQ3,countQ1,count_max,count_min]with open(path+"/box_new.txt", "a",encoding='utf-8') as f:f.write("\n%s的箱型图分布统计如下:"%con)f.write("\n箱线图检测到的异常值如下:")f.write(str(www.introzo.com_dict()))f.write("\n落入中位数到上四分位距有%d条,具体如下:"%countQ3)f.write(str(www.introzo.com_dict()))f.write("\n落入中位数到下四分位距有%d条,具体如下:" % countQ1)f.write(str(www.introzo.com_dict()))f.write("\n落入上四分位数到最大值有%d条,具体如下:" % count_max)f.write(str(data_www.introzo.com_dict()))f.write("\n落入下四分位数到最小值有%d条,具体如下:" % count_min)f.write(str(data_www.introzo.com_dict()))return outliers,stat_ll

2. 正态分布

def OutlierDetection_std(df,con,path):# 计算均值 u = df.mean()# 计算标准差 std = df.std()# 计算 P 值 res = kstest(df, 'norm', (u , std))[1]if res <= 0.05:#判断是不是符合正态分布# 定义3σ法则识别异常值# 识别异常值error_low = df[np.abs(df - u) > 2 * std]error_high = df[np.abs(df - u) > 3 * std]# 消除异常值,保留正常数据 #data_normal = df[np.abs (df ​​- u) <= 3 * std]with open(path+"/std_outliers.txt", "a",encoding='utf-8') as f:f.write("\n%s 符合正常分布:"%con)f.write("\n2sigma异常值如下:")f.write(str(error_www.introzo.com_dict()))f.write("\n3sigma异常值如下:")f .write(str( error_www.introzo.com_dict()))return u, std, error_low, error_highelse:www.introzo.com('该数据不服从正态分布----------')return None

3。正态分布结合四分位距(网上看到一篇文章,但没有实际使用过)

def box_3Sigma(df,sigma):Q1 = df.quantile(q=0.25)Q3 = df.quantile(q=0.75)IQR = Q3 - Q1min = Q1 - 1.5 * IQRmax = Q3 + 1.5 * IQRratio = 0.3低 = 3*sigma * 比率 + 最小值 * (1 - 比率)高 = 3*sigma * 比率 + 最大值 * (1 - 比率)

关灯