基础知识

在数据清洗过程中,主要处理的是缺失值,异常值和重复值。所谓清洗,是对数据进行丢弃,填充,替换,去重等操作,实现去除异常,纠正错误,补足缺失的目的。

数据缺失分为2种:

  1. 行记录的缺失,这种情况又称为数据记录丢失;
  2. 数据列值的丢失,即由于各种原因导致的数据记录种某些列的值缺失。
    这里重点讨论数据列类型缺失值的处理

技术点总结

通过pd.DataFrame新建数据框;
通过df.iloc[]来选择特定的列或对象;
使用Pandas的isnull()判断值是否为空;
使用all()和any()判断每列是否包含至少1个为True或者全部为True的情况;
使用Pandas的dropna()直接删除缺失值。
使用Sklearn.preprocessing中的Imputer方法对缺失值进行填充和替换,支持3种填充方法:mean(均值),median(中位数),most_frequent(众数);
使用Pandas的fillna填充缺失值,支持更多自定义的值和常用预定义法;
通过copy获取一个对象副本,常用于原始对象和复制对象同时进行操作的场景;
通过for循环遍历可迭代的列表值。
自定义Z-Score计算公式;
通过Pandas的duplicated()判断重复数据记录;
通过Pandas的drop_duplicates()删除重复记录,可指定特定的列或全部。

数据列缺失的处理方法

1、丢弃(缺失值处理)

1、生成一份随机数据


import numpy as np  # 导入Numpy库
import pandas as pd  # 导入Pandas库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print("生成缺失数据:")
print(df)

在这里插入图片描述

2、查看哪些值缺失

# 查看哪些值缺失
nan_all = df.isnull() # 获取所有数据框中的N值
print("查看哪些值缺失:")
print(nan_all) # 打印输出

在这里插入图片描述

3、获得含有NA的列

# 获得含有NA的列
nan_col = df.isnull().any()  # 查找含有至少1个缺失值的列,any()方法用来返回指定轴中的任何元素为True
print("获得含有NA的列")
print(nan_col)

在这里插入图片描述

4、获取全部为NA的列

# 获得全部为NA的列
nan_col2 = df.isnull().all() 
# 查找全部缺失值的列,其中all()方法用来返回指定轴的所有元素都为True
print("获取全部为NA的列")
print(nan_col2)

在这里插入图片描述

5、丢弃缺失值

df2 = df.dropna() # 直接丢弃含有NA的行记录
print(df2)

在这里插入图片描述

2、补全(缺失值处理)

相对于丢弃而言,补全是更加常用的缺失值处理方式,常用的补全方法有:

  1. 统计法:对于数值行的数据,使用均值,加权均值,中位数等方法补足;对于分类型数据,使用类别众数最多的值补足。
  2. 模型法
  3. 专家补全法
  4. 其他方法

1、使用sklearn将缺失值替换为特定值

使用这一列的均值代替NaN
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

nan_model = Imputer(missing_values='NaN', strategy='mean', axis=0) # 建立替换规则:将值为Nan的缺失值用均值做替换
nan_result = nan_model.fit_transform(df) # 应用模型规则
print("使用这一列的均值代替NaN")
print(nan_result)

在这里插入图片描述

使用这一列的中位数代替NaN
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

nan_model = Imputer(missing_values='NaN', strategy='median', axis=0) # 建立替换规则:将值为Nan的缺失值用均值做替换
nan_result = nan_model.fit_transform(df) # 应用模型规则
print("使用这一列的中位数代替NaN")
print(nan_result)

在这里插入图片描述

使用这一列的众数代替NaN
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

nan_model = Imputer(missing_values='NaN', strategy='most_frequent', axis=0) # 建立替换规则:将值为Nan的缺失值用均值做替换
nan_result = nan_model.fit_transform(df) # 应用模型规则
print("使用这一列的众数代替NaN")
print(nan_result)

在这里插入图片描述

2、使用Pandas将缺失值替换为特定值

Pandas对缺失值的处理方法是df.fillna(),该方法中最主要的两个参数是:value和method。前者通过固定的值(或手动指定)替换缺失值,后者通过使用Pandas提供的默认方法替换缺失值,以下是methods支持的方法:

pad和ffill:使用前面的值替换缺失值
backfill和bfill:使用后面的值替换缺失值

用后面的值替换缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 用后面的值替换缺失值
nan_result_pd = df.fillna(method='backfill') 
print(nan_result_pd)

在这里插入图片描述

用后面的值替换缺失值,限制每列只能替换一个缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 用后面的值替换缺失值,限制每列只能替换一个缺失值
nan_result_pd = df.fillna(method='bfill', limit=1) 
print(nan_result_pd)

在这里插入图片描述

用前面的值替换缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 用前面的值替换缺失值
nan_result_pd = df.fillna(method='pad') 
print(nan_result_pd)

在这里插入图片描述

用0替换缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 用0替换缺失值
nan_result_pd = df.fillna(0) 
print(nan_result_pd)

在这里插入图片描述

用不同值替换不同列的缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 用不同值替换不同列的缺失值
nan_result_pd = df.fillna({'col2':1.1, 'col4':1.4}) 
print(nan_result_pd)

在这里插入图片描述

用平均数代替,选择各自列的均值替换缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 用平均数代替,选择各自列的均值替换缺失值
nan_result_pd = df.fillna(df.mean()['col2':'col4']) 
print(nan_result_pd)

在这里插入图片描述

使用replace方法替换缺失值
import pandas as pd # 导入Pandas库
import numpy as np # 导入Numpy库
from sklearn.preprocessing import Imputer # 导入sklearn.preprocessing中的Imputer库

# 生成缺失数据
df = pd.DataFrame(np.random.randn(6, 4), columns=['col1','col2','col3','col4']) # 生成一份数据

df.iloc[1, 1] = np.nan #增加缺失值
df.iloc[4, 3] = np.nan
print(df)

# 使用replace方法替换缺失值
nan_result_pd = df.replace(np.nan, 0)
print(nan_result_pd)

在这里插入图片描述

3、异常值处理

知识点

异常值也称为离群点,就是那些远离绝大多数样本点的特殊群体,通常这样的数据点在数据集中都表现出不合理的特性。如果忽视这些异常值,在某些建模场景下就会导致结论的错误(如线性回归模型、K均值聚类等),所以在数据的探索过程中,有必要识别出这些异常值并处理好它们。

异常值的识别可以借助于图形法(如箱线图、正态分布图)和建模法(如线性回归、聚类算法、K近邻算法)
参考文章——Python数据清洗(三):异常值识别与处理

1、箱线图

箱线图技术实际上就是利用数据的分位数识别其中的异常点,该图形属于典型的统计图形,在学术界和工业界都得到广泛的应用
在这里插入图片描述
图中的下四分位数指的是数据的25%分位点所对应的值(Q1);中位数即为数据的50%分位点所对应的值(Q2);上四分位数则为数据的75%分位点所对应的值(Q3);上须的计算公式为Q3+1.5(Q3-Q1);下须的计算公式为Q1-1.5(Q3-Q1)。其中,Q3-Q1表示四分位差。如果采用箱线图识别异常值,其判断标准是,当变量的数据值大于箱线图的上须或者小于箱线图的下须时,就可以认为这样的数据点为异常点。

所以,基于上方的箱线图,可以定义某个数值型变量中的异常点和极端异常点,它们的判断表达式如下表所示:
在这里插入图片描述在Python中可以使用matplotlib模块实现数据的可视化,其中boxplot函数就是用于绘制箱线图的。

2、正态分布图法

根据正态分布的定义可知,数据点落在偏离均值正负1倍标准差(即sigma值)内的概率为68.2%;数据点落在偏离均值正负2倍标准差内的概率为95.4%;数据点落在偏离均值正负3倍标准差内的概率为99.6%。

所以,换个角度思考上文提到的概率值,如果数据点落在偏离均值正负2倍标准差之外的概率就不足5%,它属于小概率事件,即认为这样的数据点为异常点。同理,如果数据点落在偏离均值正负3倍标准差之外的概率将会更小,可以认为这些数据点为极端异常点。为使读者直观地理解文中提到的概率值,可以查看标准正态分布的概率密度图,如下图所示:

在这里插入图片描述利用正态分布的知识点,结合pyplot子模块中的plot函数绘制折线图和散点图,并借助于两条水平参考线识别异常值或极端异常值。

3、通过Z-Score方法判断异常值

有关异常值的确定有很多规则和方法,这里使用Z标准化得到的阈值作为判断标准,当标准化后的得分超过阈值则为异常。

示例中,阈值的设定是确定异常与否的关键,通常当阈值大于2时,已经是相对异常的表现值

import pandas as pd # 导入Pandas库

#生成异常数据
df = pd.DataFrame({'col1':[1, 120, 3, 5, 2, 12, 13], 'col2':[12, 17, 31, 53, 22, 32, 43]})
print(df)



df_zscore = df.copy() # 复制一个用来存储Z-Score得分的数据框
cols = df.columns # 获得数据框的列名
print(cols)
for col in cols: # 循环读取每列
    df_col = df[col] # 得到每列的值
    z_score = (df_col - df_col.mean()) / df_col.std() # 计算每列的z-score得分
    df_zscore[col] = z_score.abs() > 2.2 # 判断Z-Score得分是否大于2.2,如果是则为True,否则则为False
print(df_zscore)

在这里插入图片描述
上述示例中,阈值的设定是确定异常与否的关键,通常当阈值大于2时,已经是相对异常的表现值
 在判断异常值主要考虑的关键点是:如 何 判 断 异 常 值 \color{red}{如何判断异常值}如何判断异常值 。对于有固定业务规则的可以直接套用业务规则,而对于没有固定业务规则的,可以采用常见的数据模型进行判断,即基于概率分布的模型(例如正态分布的标准差范围),基于聚类的方法(例如KMeans),基于密度的方法(例如LOF),基于分类的方法(KNN),基于统计的方法(例如分位数法)等,此时异常值的定义带有较强的主观判断色彩,具体需要根据实际情况选择。

4、重复值处理

1、判断重复数据

import pandas as pd 

# 生成重复数据
data1 = ['a', 3]
data2 = ['b', 2]
data3 = ['a', 3]
data4 = ['c', 2]
df = pd.DataFrame([data1, data2, data3, data4], columns=['col1','col2'])
print(df)



isDuplicated = df.duplicated() # 判断重复数据记录
print(isDuplicated)

在这里插入图片描述

2、删除重复值

删除数据记录中所有列值相同的记录
import pandas as pd 

# 生成重复数据
data1 = ['a', 3]
data2 = ['b', 2]
data3 = ['a', 3]
data4 = ['c', 2]
df = pd.DataFrame([data1, data2, data3, data4], columns=['col1','col2'])
print(df)


new_df1 = df.drop_duplicates() # 删除数据记录中所有列值相同的记录
print(new_df1)


在这里插入图片描述

删除数据记录中col1值相同的记录
import pandas as pd 

# 生成重复数据
data1 = ['a', 3]
data2 = ['b', 2]
data3 = ['a', 3]
data4 = ['c', 2]
df = pd.DataFrame([data1, data2, data3, data4], columns=['col1','col2'])
print(df)

#删除数据记录中col1值相同的记录
new_df2 = df.drop_duplicates(['col1'])
print(new_df2)

在这里插入图片描述

删除数据记录中指定列(col1/col2)值相同的记录
import pandas as pd 

# 生成重复数据
data1 = ['a', 3]
data2 = ['b', 2]
data3 = ['a', 3]
data4 = ['c', 2]
df = pd.DataFrame([data1, data2, data3, data4], columns=['col1','col2'])
print(df)

#删除数据记录中指定列(col1/col2)值相同的记录
new_df4 = df.drop_duplicates(['col1','col2'])
print(new_df4)

在这里插入图片描述

在数据预处理阶段,对于具有缺失值的数据记录不做处理,也是一种思路。这种思路主要看后期的数据分析和建模应用,很多模型对于缺失值有容忍度或灵活的处理方法,因此在预处理阶段可以不做处理。

常见的能自动处理缺失值的模型如下:

  1. 忽略,缺失值不参与距离计算,例如KNN;
  2. 将缺失值作为分布的一种状态,并参与到建模过程,例如各种决策树及其变体;
  3. 不基于距离做计算,因此基于值的距离做计算,本身的影响就消除,例如DBSCAN。
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐