欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python数据分析:异常值检验的两种方法 -- Z 分数 & 上下分位点(放入自写库,一行代码快速实现)

程序员文章站 2022-07-14 15:42:44
...

Python数据分析:异常值检验的两种方法 -- Z 分数 & 上下分位点(放入自写库,一行代码快速实现)

引言

  数据预处理时,异常值的存在可能对最终建立的模型的精度和泛化能力有较大的影响。检测异常值的方式有很多,最基本的两种方法为 z 分数法和上下截断点法。

对 z 分数法还存在些许疑虑的可查看如下博文

统计学: Z 分数 & 正态分布 (附 Python 实现代码) --Z 检验先修; Z 分数与正态分布两者关系; Z 分数与百分位数的异同;面试要点(以心理学实验为舟)

  本文针对这两种方法,构造自写库,最终实现函数的快捷调用,在很大程度上提高了数据预处理的效率。


效果展示(Jupyter notebook)

Python数据分析:异常值检验的两种方法 -- Z 分数 & 上下分位点(放入自写库,一行代码快速实现)
一行代码快速绘图查看房价分布情况
Python数据分析:异常值检验的两种方法 -- Z 分数 & 上下分位点(放入自写库,一行代码快速实现)
如何一步到位的画出复杂精美的图片可以参考这篇博文

Python 数据可视化:seaborn displot 正态分布曲线拟合图代码注释超详解(放入自写库,一行代码搞定复杂细节绘图)

以某列作为基准检测时,返回的异常值是包含该列在呢的整行完整的数据。
Python数据分析:异常值检验的两种方法 -- Z 分数 & 上下分位点(放入自写库,一行代码快速实现)
Python数据分析:异常值检验的两种方法 -- Z 分数 & 上下分位点(放入自写库,一行代码快速实现)



完整代码

  这个函数是笔者自己编写的,功能非常简单,难度中下,但实现的效果还是挺好用的,其实还有一些值得优化的地方,欢迎在评论出指出,一起交流。

# 基础库
import numpy as np
import pandas as pd

# 提高输出效率库
from IPython.core.interactiveshell import InteractiveShell # 实现 notebook 的多行输出
InteractiveShell.ast_node_interactivity = 'all' #默认为'last'

# ------------------------- 异常值检验(常规方法) ------------------------
# ================ 异常值检验函数:iqr & z分数 两种方法 =========================
def outlier_test(data, column, method=None, z=2):
    """ 以某列为依据,使用 上下截断点法 检测异常值(索引) """
    """ 
    full_data: 完整数据
    column: full_data 中的指定行,格式 'x' 带引号
    return 可选; outlier: 异常值数据框 
    upper: 上截断点;  lower: 下截断点
    method:检验异常值的方法(可选, 默认的 None 为上下截断点法),
            选 Z 方法时,Z 默认为 2
    """
    # ================== 上下截断点法检验异常值 ==============================
    if method == None:
        print(f'以 {column} 列为依据,使用 上下截断点法(iqr) 检测异常值...')
        print('=' * 70)
        # 四分位点;这里调用函数会存在异常
        column_iqr = np.quantile(data[column], 0.75) - np.quantile(data[column], 0.25)
        # 1,3 分位数
        (q1, q3) = np.quantile(data[column], 0.25), np.quantile(data[column], 0.75)
        # 计算上下截断点
        upper, lower = (q3 + 1.5 * column_iqr), (q1 - 1.5 * column_iqr)
        # 异常值所在行索引: 大于上截断点 & 小于下截断点
        outlier_index = []  # argwhere 返回索引
        outlier_upper = np.argwhere(data[column] > upper)
        outlier_lower = np.argwhere(data[column] < lower)
        outlier_index.append(outlier_upper)
        outlier_index.append(outlier_lower)
        # 写进数据框
        outlier = pd.DataFrame()
        outlier = outlier.append(data[data[column] >= upper])
        outlier = outlier.append(data[data[column] <= lower])
        print(f'第一分位数: {q1}, 第三分位数:{q3}, 四分位极差:{column_iqr}')
        print(f"上截断点:{upper}, 下截断点:{lower}")
        return outlier, upper, lower
    # ===================== Z 分数检验异常值 ==========================
    if method == 'z':
        """ 以某列为依据,传入数据与希望分段的 z 分数点,返回异常值索引与所在数据框 """
        """ 
        params
        data: 完整数据
        column: 指定的检测列
        z: Z分位数, 默认为2,根据 z分数-正态曲线表,可知取左右两端的 2%,
           根据您 z 分数的正负设置。也可以任意更改,知道任意顶端百分比的数据集合
        """
        print(f'以 {column} 列为依据,使用 Z 分数法,z 分位数取 {z} 来检测异常值...')
        print('=' * 70)
        # 计算两个 Z 分数的数值点
        mean, std = np.mean(data[column]), np.std(data[column])
        upper, lower = (mean + z * std), (mean - z * std)
        print(f"取 {z} 个 Z分数:大于 {upper} 或小于 {lower} 的即可被视为异常值。")
        print('=' * 70)

        # 异常值所在行索引列:数据大于你设置的x个z分数点的数据 + 小于x个z分数点的数据
        outlier_index = []
        outlier_upper = np.argwhere(data[column] >= upper)
        outlier_lower = np.argwhere(data[column] <= lower)
        outlier_index.append(outlier_upper)
        outlier_index.append(outlier_lower)
        # 写进数据框
        outlier = pd.DataFrame()
        outlier = outlier.append(data[data[column] >= upper])
        outlier = outlier.append(data[data[column] <= lower])
        
        return outlier, upper, lower

值得注意的是, 如果确定了是用 z-score 或者 iqr 法,注意只是处理一次即可。只要是再次检测,就又会有 “ 新的 ” 异常值出现,因为 z-score/iqr 的计算公式会根据第一次处理后的新的样本集来弄。



后记

  数据分析,商业实践,数据可视化,网络爬虫,统计学,Excel,Word, 社会心理学,认知心理学,行为科学,民族意志学 各种专栏后续疯狂补充

  欢迎评论与私信交流!

相关标签: # 数据预处理