Python数据清洗 | 常用的数据清洗方法

常用的数据清洗方法

本文首发于微信公众号《Python希望社》,欢迎关注,完整详细的原文链接请点击这里

在数据处理的过程中,一般都需要进行数据的清洗工作,如数据集是否存在重复、是否存在确实、数据是否具有完整性和一致性、数据中是否存在异常值等。当发现数据中存在如上可能的问题时,都需要有针对性地处理。

本文大纲如下: 全文共5746字。

认真阅读本文你将掌握常用的数据清洗方法和策略

常用的数据清洗方法
重复观测处理
检测
处理
缺失值处理
数据过滤/删除法dropna
数据填充 / 替换法fillna
插值法
异常值处理
异常值检测
异常值处理及其前后对比

一、重复观测处理

重复观测是指观测行存在重复的现象,重复观测的存在会影响数据分析和挖掘结果的准确性,所以在进行数据分析和建模之前都需要进行观测的重复性检验,如果存在重复观测,还需要进行重复项的删除。

1.1处理方法

(1)检测重复观测

pandas中使用duplicated方法,该方法返回的是数据行每一行的检验结果,即每一行返回一个bool值;

(2)处理重复观测

使用drop_duplicated方法移除重复值。

1.2 案例展示(电商类APP相关数据)

(1)待清洗的原始数据


原始数据

可以看出,**浅绿色 ** 突出显示数据行为重复观测示例。为此进行如下处理:

(2)重复观测处理示例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BSli6Jji-1615030308261)(F:\Typroa\微信公众号\1-向希望\数据清洗\2.gif)]

(3)源码

import pandas as pd
# load data
data = pd.read_excel('1.xlsx')
data
#----------------------------------------------------
# 判断是否存在重复观测
print('是否存在重复观测:',any(data.duplicated()))
#----------------------------------------------------
# 处理重复观测
data.drop_duplicates(inplace=True) # inplace=True时直接删除data中重复的数据
data
#----------------------------------------------------
## 将处理后的数据 重新保存
f = pd.ExcelWriter('data_processed.xlsx')   # 创建文件对象
data.to_excel(f)                            # 将处理后的data写入新建的excel中
f.save()                                    # 保存文件

二、缺失值处理

数据缺失在大部分数据应用中都很常见,Pandas使用浮点值NaN表示浮点或非浮点数组中的缺失数据,Python内置的None值也会被当作缺失值处理。

2.1 检测数据缺失

Pandas使用方法isnull检测是否为缺失值,检测对象的每个元素返回一个bool值。

结果演示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GYeE7G0Y-1615030308266)(F:\DataCodes\《Codes》\Codes_from_JupyterNotebook\xxw_data_processing\22.gif)]

从上面的结果可以看出:data 数据中的第2个、第四个都被视为缺失值。(源码如下)

# 导入包库
import numpy as np
import pandas as pd
# 生成原始测试数据
data = pd.Series([10.0, None, 20,np.NaN, 30])
data
#----------------------------------------------------
print(data.isnull())
#----------------------------------------------------
print("是否存在缺失值:",any(data.isnull()))

2.2 处理数据缺失

对于缺失值一般可以采用三种方法,分别是过滤法、填充法和插值法。在这里我们分别给出每种方法的内容和案例展示(附源码)

(1)数据过滤 / 删除法 (dropna)

是指当缺失的观测比例非常低时(如5%以内),直接删除存在缺失的观测;或者当某些变量的缺失比例非常高时(如85%以上),直接删除这些缺失的变量。

数据过滤dropna方法的语法格式如下

dropna(axis = 0, how = 'any', thresh = None)
## -------- 参数注释 -----------
# (1)axis = 0 表示删除行(记录);axis = 1 表示删除列(变量)
# (2)how 参数可选值为 any 或 all, all 表示删除全有NaN的行
# (3)thresh 为整数类型,表示删除的条件,如thresh = 3,表示一行中至少有3个非NaN值时,才将其保留。

要查看关于 dropna方法的帮助,可以使用下面命令:(其他命令同理)

import pandas
help(pd.DataFrame.dropna)
案例展示:

原始数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8XhggXIW-1615030308270)(F:\DataCodes\《Codes》\Codes_from_JupyterNotebook\xxw_data_processing\222.gif)]

源码
import pandas as pd
a = pd.read_excel('3.xlsx',usecols = range(1,4))   # 提取 第2列到第4列的数据
a
#-------------------------------------
b1 = a.dropna()    # 删除所有的缺失值
print(b1)
#-------------------------------------
b2 = a.dropna(axis = 1, thresh = 9)  # 删除有效数据个数小于 9 的列
print(b2)
#-------------------------------------
b3 = a.drop('用户B', axis = 1)   # 删除用户B的数据
print(b3)

(2)数据填充 / 替换法 (fillna

是指用某种常数直接替换那些缺失值,例如,对于连续变量而言,可以使用均值或中位数替换;对于离散变量,可以使用众数替换。

当数据中出现缺失值时,还可以用其他的数值进行填充,常用的方法是 fillna, 其基本语法格式为:

fillna(value = None, method = None, axis = None, inplace = False)
# 其中value值除基本类型外,还可以使用字典,这样可以实现对不同的列填充不同的值。method表示采用的填补数据的方法,默认是None。

下面通过示例说明fillna 的用法。

案例展示:

原始数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bmpxEsaQ-1615030308274)(F:\DataCodes\《Codes》\Codes_from_JupyterNotebook\xxw_data_processing\2222.gif)]

源码
import pandas as pd
a = pd.read_excel('4.xlsx')
a
#----------------------------
b1 = a.fillna(0)  							# 用 0 填补所有的缺失值
b2 = a.fillna(method = 'ffill') 			# 用前一行的值填补缺失值
b3 = a.fillna(method = 'bfill') 			# 用后一行的值填补,最后一行缺失值不处理	
b4 = a.fillna(value = {
    
    'gender':a.gender.mode()[0],'age':a.age.mean(),'income':a.income.median()})
## 性别使用众数替换 年龄使用均值替换 收入使用中位数替换
#----------------------------
print(b1,'\n----------------------------\n',b2,'\n----------------------------\n',b3,'\n----------------------------\n',b4)

(3)插值法

插值法是指根据其他非缺失的变量或观测来预测缺失值,常见的插值法有线性插值法、K近邻插值法、Lagrange插值法等。

当出现缺失值时,也可以使用插值法对缺失值进行插补,插值的数学原理在 其中的插值方法可以使用:‘linear’, ‘nearest’, ‘zero’, ‘slinear’, ‘quadratic’,‘cubic’,‘spline’,‘barycentric’,‘polynomial’.

案例演示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1uEp6nC-1615030308277)(F:\DataCodes\《Codes》\Codes_from_JupyterNotebook\xxw_data_processing\22222.gif)]

源码
import pandas as pd
a = pd.read_excel('4.xlsx')
a
# ----------------------------------
import numpy as np
b = a.fillna(value = {
    
    'gender':a.gender.mode()[0],                              # 性别使用众数替换
                      'age':a.age.interpolate(method = 'polynomial',order = 2), # 年龄使用 二次多项式插值 替换
                      'income':a.income.interpolate()})                         # 收入使用线性插值替换 

三、异常值处理

异常值(Outlier)是指哪些远离正常值的预测,即“不合群”观测。异常值的出现会对模型的创建和预测产生严重的后果。当然异常值的出现也不一定都是坏事,有些情况下,通过寻找异常值就能够给业务带来良好的发展,如【销毁“钓鱼网站”,关闭“薅羊毛”用户的权限等】

对于异常值的检测,一般采用两种方法,一种是标准差法,另一种是箱线图判别法。标准差法的判别公式是: outlier > x ^ + n σ \text{outlier}>\hat{x}+n\sigma outlier>x^+nσ 或者 outlier < x ^ − n σ \text{outlier}<\hat{x}-n\sigma outlier<x^nσ , 其中 outlier < x ^ − n σ \text{outlier}< \hat x -n\sigma outlier<x^nσ , 其中 x ^ \hat{x} x^ 是均值, σ \sigma σ是样本标准差。当 n = 2 n=2 n=2 时, 满足条件的观测就是异常值;当 n = 3 n=3 n=3 时,满足条件的观测即是极端异常值。

箱线图的判别公式是: outlier > Q 3 + n IQR \text{outlier}>Q_3+n\text{IQR} outlier>Q3+nIQR outlier < Q 1 − n IQR \text{outlier}<Q_1-n\text{IQR} outlier<Q1nIQR , 其中 Q 1 Q_1 Q1 为下四分位数(25%), Q 3 Q_3 Q3 为上四分位数(75%), IQR \text{IQR} IQR 为上四分位数与下四分位数的差。当$ n=1.5 时 , 满 足 条 件 的 观 测 为 异 常 值 , 当 时,满足条件的观测为异常值,当 n=3$ 时,满足条件的观测为极端异常值。

这两种方法的选择标准如下,如果数据近似服从正态分布,因为数据的分布相对比较对称,优先选择标准差法。否则优先选择箱线图法,因为分位数并不会收到极端值的影响。当数据存在异常时,若异常观测的比例不要打,一般可以使用删除法将异常值删除;也可以使用替换法,可以考虑使用低于判别上限的最大值替换上端异常值、高于判别下限的最小值替换下端异常值,或使用均值或中位数替换等。

3.1 案例展示:

(1)异常值检测

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6diSHbF-1615030308278)(F:\DataCodes\《Codes》\Codes_from_JupyterNotebook\xxw_data_processing\222222.gif)]

原始数据和异常值检验结果


原始数据

直方图与核密度图

(2)异常值的处理及其前后对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFOaax3T-1615030308279)(F:\DataCodes\《Codes》\Codes_from_JupyterNotebook\xxw_data_processing\2222222.gif)]

count mean std min 25% 50% 75% max
替换前 289 48.6135 39.4741 0 15.6 39 68.9 190.2
替换后 289 48.0660 37.9189 0 15.6 39 68.9 141.7

源码如下:

# =============================================
# 异常值检测
# =============================================
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
a = pd.read_csv('ISSN_Y_tot.csv')
a
#---------------------------------------------
plt.plot(a.counts)
plt.show()
#---------------------------------------------
mu = a.counts.mean()  # 计算黑子 个数年平均值
s = a.counts.std()    # 计算黑子个数标准差
print('标准差法异常值上限检测:',any(a.counts>mu+2*s))  # 输出: True
print('标准差法异常值下限检测:',any(a.counts<mu-2*s))  # 输出: False
#---------------------------------------------
Q1 = a.counts.quantile(0.25) # 计算下四分位数
Q3 = a.counts.quantile(0.75) # 计算上四分位数
IQR = Q3 - Q1
print("箱线图法异常值上限检测:",any(a.counts> Q3 + 1.5*IQR))  # 输出:  True
print("箱线图法异常值下限检测:",any(a.counts< Q1 - 1.5*IQR))  # 输出:  False
#---------------------------------------------
plt.style.use('ggplot')     # 设置绘图风格
a.counts.plot(kind = 'hist', bins = 30 , density = True)    # 绘制直方图
a.counts.plot(kind = 'kde')                                 # 绘制核密度曲线
plt.show()
# =============================================
#  异常值处理
# =============================================
print('异常值替换前的数据统计特征',a.counts.describe())
#---------------------------------------------
UB = Q3 + 1.5 * IQR;
st = a.counts[a.counts < UB].max()
print('判别异常值的上限临界值为:',UB)
print('用以替换异常值的数据为:',st)
#---------------------------------------------
a.loc[a.counts>UB,'counts'] = st      # 替换超过判别上限异常值
print('异常值替换后的数据特征\n',a.counts.describe())
参考文献

司首奎,孙玺菁.《Python数学实验与建模》. 北京:科学出版社,2020

推文中所涉及到的所有 数据集和全部源代码 均可通过在后台回复关键字”数据清洗“获得。

猜你喜欢

转载自blog.csdn.net/GODSuner/article/details/114447458