pandas数据分析库

数据清洗

概述

数据清洗是指对原始数据进行处理和转换,以去除无效、重复、缺失或错误的数据,使数据符合分析和建模的要求。

作用和意义

  • 提高数据质量:
  • 通过数据清洗,数据质量得到提升,减少错误分析和错误决策。
  • 增加数据可用性:
  • 清洗后的数据更加规整和易于使用,提高数据的可用性和可读性。
  • 支持分析和建模:
  • 清洗数据是进行数据分析和建模的前置步骤,只有高质量的数据才能得到准确和可靠的分析结果。
  • 保护隐私和数据安全:
  • 在数据清洗过程中可以对敏感数据进行匿名化或删除,保护隐私和数据安全。

清洗维度

  • 缺失值处理:
  • 对于缺失的数据,可以删除包含缺失值的行或列或者填充缺失值。
  • 重复值处理:
  • 识别和删除重复的数据行,避免重复数据对分析结果产生误导。
  • 异常值处理:
  • 检测和处理异常值,决定是删除、替换或保留异常值。

缺失值清洗

缺失值/空值的删除
  • 伪造缺失值数据
import pandas as pd
from pandas import DataFrame,Series
import numpy as np

df = DataFrame(data=np.random.randint(0,100,size=(7,5)))
df.iloc[0,3] = np.nan
df.iloc[3,3] = None
df.iloc[2,2] = np.nan
df.iloc[5,3] = np.nan
df
  • 缺失值的检测和删除
相关方法:
- isnull():检测df中的每一个元素是否为空值,为空则给该元素返回True,否则返回False
- notnull():检测df中的每一个元素是否为非空值,为非空则给该元素返回True,否则返回False
- any():检测一行或一列布尔值中是否存在一个或多个True,有则返回True,否则返回False
- all():检测一行或一列布尔值中是否存全部为True,有则返回True,否则返回False
- dropna():将存在缺失值/空值的行或者列进行删除
  • isnull()结合any()进行空值检测和过滤
ex = df.isnull().any(axis=1)#检测空值对应的行,轴向0表示行,1表示列
drop_index = df.loc[ex].index#获取空值对应的行索引
df.drop(index=drop_index)#删除空值对应的行
  • notnull()结合all()进行空值检测和过滤
ex = df.notsnull().all(axis=1)#检测空值对应的行,轴向0表示行,1表示列
df.loc[ex]#过滤空值对应的行
  • dropna()进行空值检测和过滤
df.dropna(axis=0) #注意在dropna中的轴向0表示行,1表示列
  • 计算df中每一列存在缺失值的个数和占比
for col in df.columns:
    #col表示df的某一列的列索引
    #判断列中是否存在空值
    if df[col].isnull().sum() > 0:
        #计算空值的占比
        p = df[col].isnull().sum() / df[col].size
        #将p小数转换成百分比显示
        p = format(p,'.2%') #.2%表示将p转换成保留2位小数的百分数
        print(col,'列中存在空值的占比为:',p)
缺失值/空值的填充
相关方法:
    - fillna(value,method,axis)
参数介绍:
    - value:给空值填充的值
    - method:填充方式,可以为bfill向后填充和ffill向前填充
    - axis:填充轴向
  • 使用任意值填充空值
df.fillna(value=666) #将df中所有的空值填充为666
  • 使用近邻值填充空值
df.fillna(method='bfill',axis=0) #在竖直方向上选择空后面的元素填充空值
#method填充方式:ffill(向前填充)和bfill(向后填充)
  • 使用相关的统计值填充空值
#使用列的均值填充列的空值
for col in df.columns:
    if df[col].isnull().sum() > 0:
        mean_value = df[col].mean()
        df[col].fillna(value=mean_value,inplace=True)

注意:实现空值的清洗最好选择删除的方式,如果删除的成本比较高,再选择填充的方式。

重复值清洗

  • 伪造重复行的数据源
df = DataFrame(data=np.random.randint(0,100,size=(8,5)))
df.iloc[3] = [0,0,0,0,0]
df.iloc[5] = [0,0,0,0,0]
df.iloc[7] = [0,0,0,0,0]
  • 使用duplicated()方法检测重复的行数据
#可以检测原始数据中哪些行是重复,重复则返回True,否则返回False
df.duplicated() 
  • 使用drop_duplicates()方法检测且删除重复的行数据
df.drop_duplicates(inplace=True)

异常值清洗

异常值是分析师和数据科学家常用的术语,因为它需要密切注意,否则可能导致错误的估计。 简单来说,异常值是一个观察值,远远超出了样本中的整体模式。

异常值在统计学上的全称是疑似异常值,也称作离群点,异常值的分析也称作离群点分析。异常值是指样本中出现的“极端值”,数据值看起来异常大或异常小,其分布明显偏离其余的观测值。异常值分析是检验数据中是否存在不合常理的数据。

  • 给定条件的异常数据处理
  • 自定义一个1000行3列(A,B,C)取值范围为0-1的数据源,然后将C列中的值大于其两倍标准差的异常值进行清洗
data = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C'])
#求出了C列数据的2倍标准差
twice_std = data['C'].std() * 2
ex = data['C'] > twice_std
indexs = data.loc[ex].index #取出了异常值对应行数据的行索引
data.drop(index=indexs,inplace=True) #在原始数据中将异常值对应的行数据进行清洗
  • 未给定条件的异常值处理

  • 标准差法

    • 又称为拉依达准则(标准差法),对某些异常数据进行剔除,以提高数据的准确性。

    • 适用场景:

    • 仅局限于对正态或近似正态分布的样本数据处理,且数据量级尽可能大会更加适用。

    • 工作原理:

    • 先假设一组检测数据存在异常数据,对其进行计算处理得到标准偏差σ(sigma),然后确定一个区间,认为凡超过这个区间的就是异常数据,则对该数据予以剔除。

    • 标准差本身可以体现因子的离散程度,是基于因子的平均值μ而定的。在离群值处理过程中,可通过用μ ± nσ来衡量因子与平均值的距离。

      • n通常使用3:这是一个相对比较保守的选择,也是基于统计学中正态分布的性质。
      在正态分布中,约68%的数据落在平均值(μ)加减一个标准差(σ)的范围内,约95%的数据落在平均值加减两个标准差的范围内,约99.7%的数据落在平均值加减三个标准差的范围内。因此,3倍标准差的阈值范围可以涵盖绝大部分的正态分布数据。
      
      • 将区间[μ - 3σ,μ + 3σ],的值视为正常值范围,在[μ - 3σ,μ + 3σ]外的值视为离群值

      Snip20230925_277

      #伪造了一组含有5个异常数据的样本
      iris_length = abs(np.random.randn(9999))
      #手动添加一些异常数据
      iris_length[44] = 54
      iris_length[33] = 67
      iris_length[22] = 56
      iris_length[11] = 87
      iris_length[55] = 49
      
      def std_opt(data):
          mean_value = data.mean()#均值
          std_value = data.std() #标准差
          m_min = mean_value - 3*std_value
          m_max = mean_value + 3*std_value
          return m_min,m_max
      
      m_min,m_max = std_opt(iris_length)
      
      for i in iris_length:
          if i < m_min or i > m_max:
              print(i)
      
  • MAD法

    • 又称为绝对值差中位数法,是一种先需计算所有因子与中位数之间的距离总和来检测离群值的方法,适用大样本数据

    • 公式:设有平稳离散数据X=[x1,x2,…,xn],其数据中位数为X_median:

      Snip20230925_278

    • 应用场景:

    • 当数据呈对称分布或接近对称分布时MAD和标准差法效果相等或接近相等

    • 当数据为偏态分布,应选择众数或中位数等位置代表值,这时它们的代表性要比均值好。

      def median_opt(data):
        median = np.median(data)
        count = data.size
        a = (((data-median)**2).sum()/count)**0.5
        m_min = median - 3*a
        m_max = median + 3*a
        return m_min,m_max
      
      m_min,m_max = median_opt(iris_length)
      for i in iris_length:
        if i < m_min or i > m_max:
            print(i)
      
  • 四分位数法

    • 又叫做箱型图法,由最小值、下四分位值(25%),中位数(50%),上四分位数值(75%),最大值这5个关键的百分数统计值组成的。

    • 如何通过箱形图判断异常值呢?

    • 假设下四分位值为Q1,上四分位数值为Q3,四分位距为IQR(其中IQR=Q3-Q1),推导如下:

      Snip20230925_279

    • 应用场景:适用于数据分布非正态、存在偏斜或包含极端值的情况。尤其适用于对数值型数据的异常值检测和过滤。但在对称且近似正态分布的数据上也可以使用。

      import numpy as np
      
      def boxplot(data):
        # 下四分位数值、中位数,上四分位数值
        Q1, median, Q3 = np.percentile(data, (25, 50, 75))
        # 四分位距
        IQR = Q3 - Q1
        # 内限
        inner = [Q1-1.5*IQR, Q3+1.5*IQR]
        # 外限
        outer = [Q1-3.0*IQR, Q3+3.0*IQR]
        print('>>>内限:', inner)
        print('>>>外限:', outer)
      
        # 过滤掉极端异常值
        goodData = []
        for value in data:
            if (value < outer[1]) and (value > outer[0]):
                goodData.append(value)
      
        return goodData
      
      data = [0.2, 0.3, 0.15, 0.32, 1.5, 0.17, 0.28, 4.3, 0.8, 0.43, 0.67]
      boxplot(data)