数据预处理之数据清洗

1、介绍

数据预处理的第一步数据清洗,数据清洗指删除、更正数据库中错误、不完整、格式有误或多余的数据。数据清理不仅能够更正错误,也可以加强来自各个单独信息系统不同数据间的一致性。

2、知识点

  • 数据有效性判定依据
  • 数据清洗常用方法
  • 缺失值处理
  • 重复值的处理
  • IQR 值的计算

3、数据预处理概述

原始数据一般会十分凌乱。不仅数据结构不满足需要,键值也可能存在错误甚至缺失。此时,数据预处理的重要性就突显出来了。数据预处理是一个产生有效数据的过程,即通过自动化、半自动化、甚至手动操作等手段将原始数据文件或者数据仓库里面的数据,处理成能输入到训练模型中的数据。

数据预处理是数据挖掘和模型构建过程中十分重要的步骤。对没有经过预处理的数据进行分析,结果是没有任何意义的。使用没有经过预处理的数据训练模型,最终可能得到错误的结论。因此,在对数据正式分析之前,预处理的工作必不可少。

在讨论数据预处理方法之前,我们先要明白什么是高质量的数据。一般情况下,从以下 5 个维度进行评定。

序号步骤说明
1数据清理
Data Cleansing
数据清理大致包括对空缺键值进行填充操作,
对噪声数据进行相应的平滑处理,对孤立点和异常点进行删除处理等。
2数据集成
Data Integration
将多个数据库或者数据文件里面包含的数据进行集成处理。
3数据转换
Data Transformation
将数据进行聚集或者规范化处理,从一种形式转换成另外一种我们需要的形式。
4数据规约
Data Reduction
对庞大的数据集进行压缩处理,且尽量保证最终预测结果的一致性。

与此同时,业界普遍认同数据预处理的过程将消耗整个数据分析流程的大部分时间,大约会占据 60%~80%。

首先,我们将介绍数据清洗。数据清洗是非常关键和重要的一步,它主要包括对空缺键值进行填充操作,对噪声数据进行相应的平滑处理,对孤立点和异常点进行删除处理等。

4、缺失值处理

缺失数据是数据清洗过程中常遇到的情况。数据缺失的原因多种多样,例如采集数据设备的损坏,造成某几天的数据缺失。或者是数据在传输、整理过程中造成的缺失。

对于缺失数据而言,通常都是需要处理的。在处理之前,我们先了解如何定位到缺失数据。

4.1、标记缺失数据

首先,我们生成一组包含缺失数据的示例数据。

# 导入相关的包
import numpy as np
import pandas as pd

# 生成数据
null_data = {'A': [10, np.nan, 25, np.nan, 42, np.nan],
             'B': [12, 15, np.nan, 14, 17, np.nan],
             'C': [10, 13, 27, 13, 19, 40]}

# 转化为dataframe格式
df = pd.DataFrame(null_data)
df

Pandas 对于不同类型的空值有不一样的标注,对于数值型空值会使用 NaN(Not a Number)标识,对于字符串统一采样 None 标识。可以看到,上面的示例 DataFrame 中包含 5 个 NaN 值。

当我们使用 Pandas 定位缺失数据时,通常会使用 isnull() 或者 notnull() 两种方法。二者均会返回布尔值,当我们使用 isnull() 时,返回 True 即代表是缺失值。

# True 为缺失值
df.isnull()  

如果想要统计每列包含多少个缺失值,只需要添加 sum() 即可。

 # 统计每列缺失值数量
df.isnull().sum() 

4.2、删除缺失数据

缺失值处理最简单的方法就是「不处理,直接删除」,你可能觉得这句话是个「玩笑」,其实真的存在。对于直接删除缺失数据,主要存在于以下几种情形:

  • 缺失数据占全部数据比例非常低,基本可以忽略不计,删除后且不会对整体数据分布产生影响。
  • 缺失数据因为本身特性无法填充,比如对于某些检测指标,如果填充不准确会严重影响最终结果。这种情况下,宁愿删除也不要进行处理。

Pandas 删除缺失数据的操作主要是通过 dropna() 完成。

# 删除全部存在缺失值的行
df.dropna()  

上面的操作中,我们删除了全部存在缺失值的行。实际情况中,我们可能会有下面几种删除缺失值的需求:

# 删除全部存在缺失值的列
df.dropna(axis=1)  

# 删除全部值均为缺失值的行
df.dropna(how='all')  
# 参数值换成 any 则为删除存在缺失值的行

 # 删除行,且该行非缺失值少于 2 个
df.dropna(thresh=2) 

4.3、填充缺失值

除了直接删除缺失值这种「简单又暴力」的操作,还有一种经常使用到的方法是对缺失值进行填充。而填充一般分为 3 种情况:

  • 固定值填充:人为指定,或使用行/列均值、中位数等。
  • 临近值填充:使用缺失值相临近的数值填充。
  • 数学填充:使用函数插值填充。

首先,我们学习如何使用固定值进行填充。这里可以直接使用 Pandas 提供的 replace 完成。

# 将缺失值填充为 0
df.replace(np.nan, 0)  

当然,Pandas 提供了一个专门用于填充缺失值的函数 fillna() 

# 将缺失值填充为 0
df.fillna(0)  

可以看到,效果是一样的。

如果要使用平均值或者中位数进行填充。

# 使用各列平均值填充
df.fillna(df.mean())  

# 使用各列中位数填充
df.fillna(df.median())  

当我们使用 fillna 填充缺失值时,我们还可以使用临近值填充。如果数据在短时间内的变化不大,那么临近值填充是一个很好的方式。例如气温数据的变化,如果已知 13:00 的气温而 13:15 数据缺失,那么就可以初略地使用 13:00 的气温填充 13:15 的缺失值。

同样,还是拿上面的 df 示例。

# 使用后一个临近数据向前填充
df.fillna(method='bfill')  

# 使用前一个临近数据向后填充
df.fillna(method='ffill')  

上面介绍了固定值和临近值填充方法。很多时候,数据虽然缺失但仍然能看出数据的变化趋势,此时更好的缺失值填充方法是使用数据方法进行插值。Pandas 中的 interpolate() 可以帮助我们快速应用一些常用的插值函数。

# 生成新的实例数据
sample_data = {'A': [1, np.nan, 3, np.nan, 5, 6],
               'B': [1, 4, np.nan, np.nan, 25, 36]}

df = pd.DataFrame(sample_data)
df

上面这两列示例数据,你可以看到 A 列明显是线性增加趋势,而 B 列是X平方的增加趋势。此时,如果用临近值填充显然不妥,就可以通过线性插值或者多项式插值完成。

# 线性插值
df.interpolate(method='linear')  

# 2 次函数插值
df.interpolate(method='polynomial', order=2)  

当然,你会想到怎样估计数据变化的趋势呢,关于这一点可以通过绘图等其他更为直观的方式完成。

5、重复值处理

除了缺失值,数据还容易出现另外一种情形,也就是重复值。下面,介绍以下使用 Pandas 清除重复值的方法。同样,我们先生成一组示例数据。

df = pd.DataFrame({'name': ['amy', 'david'] * 3 +
                   ['jam'], 'class': [2, 2, 2, 4, 3, 2, 4]})
df

与缺失值判断相似,你可以使用 Pandas 提供的 duplicated() 方法判断重复值,如果存在重复值则返回 True。

# 判断重复值
df.duplicated()  

# 统计判断重复值
df.duplicated().sum()  

接下来,你可以使用 drop_duplicates() 去除全部重复值。

# 去除重复值
df.drop_duplicates()  

如上所示,drop_duplicates() 在去除重复值时,会对全部列进行判断。如果你只想去除 name 列的重复值,可以单独指定。

# 去除 name 列重复值
df.drop_duplicates(['name'])  

还有一个实用的技巧在于保留缺失值的顺序。如上所示,drop_duplicates() 默认保留重复项前面的值,而去除后面的值。你可以选择保留重复值最后出现的值。

# 保留重复值最后一个
df.drop_duplicates(keep='last')  
# 参数也可以选择 first,保留重复值第一个

6、异常值处理

除了缺失值与重复值,在处理数值型数据时,我们还容易遇到一种状况,那就是异常值。异常值检测是处理数值型数据过程中必须重视的一项工作。那些在收集、录入过程中产生的异常数据,如果不及时剔除,很可能对后续的预测分析带来严重不良影响。

应用数学和统计学领域对异常值检测研究比较深入,目前存在的检测方法也非常多。大致来讲,有从概率方法入手的一元正态分布及多元高斯方法,还有通过矩阵分解和神经网络进行异常值检测的相关方法。

在这里,我们介绍一种简单直观的异常值检测方法,那就是通过箱形图(箱线图)来识别异常数据。箱形图(下方红色)是用来观测数据集分布的一种图形类型。箱形图中,从下到上(下图从左到右)依次有 6 个数据节点,分别是:下界、下四分位、均值、中位数、上四分位、上界。

如上图所示,我们可以看到正态分布及其所对应的箱形图。由于正态分布的中位数等于均值,所以上图只看到了 5 个数据节点。

四分位数,是指将一组数据值按大小排序后分成四等分,每一部分包含 1/4 的数据,这种划分的分割点就是四分位数。其中第 1 部分和第 2 部分的分割点称为第 1 分位数 Q_1, 也被称为第 25 百分位数(下四分位)。第 3 部分和第 4 部分的分割点称为第 3 四分位数 Q_3,也被称为第 75 百分位数(上四分位)。而第二部分和第三部分的分割点是第 2 四分数,也就是中位数。其中四分位距 IQR 是指第三四分位数和第一分四分位数的差,也就是 IQR = Q_3 - Q_1。

所有小于  Q_1 - 1.5IQR  或 大于  Q_3 + 1.5IQR  的数据项被称为异常值。那么,我们就可以通过该判断依据来标记异常数据。

接下来,我们可以生成一组数据,并找出异常值。

# 随机数种子
np.random.seed(10)  
# 生成一组正态分布随机数据
normal_data = np.random.randn(200)  
normal_data

 接下来,我们计算 IQR 值,以及异常值上下界限。

# 使用 numpy 提供的 percentile 方法计算百分位数
# 下四分位
Q1 = np.percentile(normal_data, 25) 
# 上四分位 
Q3 = np.percentile(normal_data, 75)  

# 计算 IQR 值
IQR = Q3 - Q1
outlier1 = Q1 - 1.5 * IQR
outlier2 = Q3 + 1.5 * IQR

# 异常值判断标准
outlier1, outlier2  

最终,我们输出原数据中大于上界与小于下界的数据。

np.append(normal_data[normal_data < outlier1],
          normal_data[normal_data > outlier2])

 如上所示,输出值即为数据集中的异常值。其实,我们可以通过 Matplotlib 绘制出上方数据的箱形图,这里会用到 boxplot() 方法。

import matplotlib.pyplot as plt
%matplotlib inline

# 绘制箱形图
box = plt.boxplot(normal_data, whis=1.5, vert=False)  
# 绘制原数据点方便对比
scatter = plt.plot(normal_data, np.linspace(1, 1, 200), 'r.', alpha=0.3)  

其实,除了上方直接计算异常点的方法。还有一种方法就是通过 Matplotlib 绘图结果获取。代码如下:

box['fliers'][0].get_xdata()

这里得到的异常值数据与上方手动计算结果一模一样。

 实际上,异常检测处理不仅仅是一种数据预处理手段,很多时候会单独以数据分析任务出现。例如:

  • 信用卡欺诈检测:信用卡是一种广泛使用的金融工具,但很多时候可能被盗用、冒用。这些问题,不仅对持卡人造成财产损失,也增加了发卡行的风险。信用卡欺诈检测就是一种发卡行对交易行为进行异常检测的应用。冒用信用卡的购买行为可能不同于持卡人不同,那么通过寻找异常交易模式,就能在关键时刻拒绝交易,尽可能保证信用卡消费安全。
  • 网络入侵检测:如今,网络攻击已成家常便饭,大国之间也经常互相指责对方实施网络攻击行为。很多时候,我们不一定需要等到网络攻击实施完成之后才后知后觉,而是借助异常检测分析网络行为、安全日志、审计数据、其它网络上可以获得的信息以及计算机系统中若干关键点的信息,检查网络或系统中是否存在违反安全策略的行为和被攻击的迹象。
  • 公共卫生安全:公共卫生安全是每个国家都极其重视和加强防范的任务,通过检测医院诊疗数据、疫苗接种数据、气候变化数据等,可以及时发现异常,并预防重大公共卫生安全事件的发生。
### 数据预处理数据清洗的概念区分 数据预处理是一个更广泛的过程,涵盖了从原始数据到可用于分析的数据的所有操作。它通常包括但不限于数据清洗、特征工程、降维以及规范化等步骤[^1]。 相比之下,数据清洗专注于解决数据中的质量问题,例如填充缺失值、去除噪声、修正不一致性和清理冗余记录等内容[^3]。因此,在某些教材中,“数据清洗”被看作是“数据预处理”的一个重要子集,这也是为何两者常共同出现在同一章节的原因。 以下是针对数据预处理数据清洗的一些具体方法和技术: #### 缺失值处理 当遇到缺失值时,可以采取多种策略来填补这些空白区域。常见的技术有删除含有缺失值的样本或特性、使用均值/中位数/众数替代缺失值等。在 MATLAB 中,如果计算平均值而发现存在 NaN 值,则表明该数值为空缺状态[^4];而在 Python 的 Pandas 库里,`fillna()` 函数提供了灵活的方式来进行替换操作。 ```python import pandas as pd df = pd.DataFrame([[1, 2], [None, 4]], columns=['A', 'B']) print(df.fillna(value={'A': df['A'].mean(), 'B': df['B'].median()})) ``` 此代码片段展示了如何利用各列统计量完成缺失值填充值的任务。 #### 异常检测与修复 除了处理丢失的信息外,还需要关注那些偏离正常范围过多的数据点——即所谓的离群点(outliers) 或者异常情况(anomalies)。通过可视化手段(如箱线图)、基于模型的方法(比如 Z-score 测试)能够有效识别此类问题,并决定保留还是剔除它们。 ```python from scipy import stats z_scores = np.abs(stats.zscore(data)) filtered_entries = (z_scores < 3).all(axis=1) cleaned_data = data[filtered_entries] ``` 上述脚本实现了基于标准分数(Z-Score)过滤掉极端值的功能。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值