第3章数据清洗与特征预处理

数据处理是建立机器学习模型的第一步,对最终结果有决定性的作用。本章重点介
绍数据清洗与特征预处理。其中,数据清洗是指对缺失值、异常值和重复值等进行处理; 
特征预处理是指通过规范化、标准化、鲁棒化和正则化等方法将数据转化成符合算法要求
的数据。最后介绍misingno库和词云,它们用于可视化显示数据相关信息。

3.数据清洗
1 

3.1 
数据清洗简介
1.
在处理数据之前,需要进行数据质量分析,了解数据的功能和作用,检查原始数据中

是否存在脏数据。脏数据一般是指不符合要求以及不能直接进行相应分析的数据。

脏数据往往存在如下问题:没有列头,一个列有多个参数,列数据的单位不统一,存
在缺失值、空行、重复数据和非ASCI 
字符,有些列头应该是数据而不应该是列名参数, 
等等。可将这些问题大致归类为缺失值、异常值和重复值等噪声数据问题。而数据清洗
就是发现并处理这些数据问题。

3.2 
评价标准
1.
对于数据的评价一般具有如下标准: 

(1)精确性。描述数据是否与其对应的客观实体的特征一致。
(2)完整性。描述数据是否存在缺失记录或缺失字段。
(3)一致性。描述同一实体的同一属性的值在不同系统中是否一致。
(4)有效性。描述数据是否满足用户定义的条件或在一定的域值范围内。
(5)唯一性。描述数据是否存在重复记录。
3.清洗方法
2 

2.缺失值
3.1 
缺失值通常是指记录的缺失和记录中某个字段信息的缺失,一般以空白、NaN或其
他占位符编码,采用删除法和数据填充进行处理。

.删除法。如果某个属性的缺失值过多,可以直接删除整个属性。
.数据填充。使用一个全局变量填充缺失值,使用属性的平均值、中间值、最大值、

57 
最小值或更为复杂的概率统计函数值填充缺失值。
常用填充方法如表3.1所示。
表3.1 常用填充方法
填充方法方法描述
平均值/中位数根据属性值的类型,用该属性取值的平均值/中位数填充
固定值将缺失的属性值用一个常量替换
最近值用最接近缺失值的属性值填补 
Sklearn中的Imputer类或SimpleImputer类用于处理缺失值。其中,Imputer在
preprocessing模块中,而SimpleImputer在sklearn.impute模块中。
Imputer具体语法如下: 
from sklearn.preprocessing import Imputer 
imp=Imputer(missing_values="NaN", strategy="mean") 
SimpleImputer具体语法如下: 
from sklearn.impute import SimpleImputer 
imp=SimpleImputer(missing_values=np.nan, strategy="mean") 
参数含义如下: 
. missing_values=np.nan:缺失值是NaN。
.strategy="mean":用平均值、中位数等填充缺失值。
【例3.1】 缺失值处理示例。 
import pandas as pd 
import numpy as np 
#from sklearn.preprocessing import Imputer 
from sklearn.impute import SimpleImputer 
df=pd.DataFrame([["XXL", 8, "black", "class 1", 22], 
["L", np.nan, "gray", "class 2", 20], 
["XL", 10, "blue", "class 2", 19], 
["M", np.nan, "orange", "class 1", 17], 
["M", 11, "green", "class 3", np.nan], 
["M", 7, "red", "class 1", 22]]) 
df.columns=["size", "price", "color", "class", "boh"] 
print(df) 
#1. 创建Imputer 
#imp=Imputer(missing_values="NaN", strategy="mean" ) 
imp=SimpleImputer(missing_values=np.nan, strategy="mean") 
#2. 使用fit_transform 函数完成缺失值填充
df["price"]=imp.fit_transform(df[["price"]]) 
print(df)

58 
【程序运行结果】 
size price color class boh 
0 XXL 8.0 black class 1 22.0 
1 L NaN gray class 2 20.0 
2 XL 10.0 blue class 2 19.0 
3 M NaN orange class 1 17.0 
4 M 11.0 green class 3 NaN 
5 M 7.0 red class 1 22.0 
size price color class boh 
0 XXL 8.0 black class 1 22.0 
1 L 9.0 gray class 2 20.0 
2 XL 10.0 blue class 2 19.0 
3 M 9.0 orange class 1 17.0 
4 M 11.0 green class 3 NaN 
5 M 7.0 red class 1 22.0 
3.2.2 异常值
异常值指录入错误以及不合常理的数据,一般采用箱形图和标准差两种办法进行识
别,分别介绍如下。
1.采用箱形图识别异常值
在箱形图中判别异常值的方法见2.5.5节。异常值用中位数填充。 
import numpy as np #导入NumPy 库
import pandas as pd #导入Pandas 库
a=data["数量"].quantile(0.75) 
b=data["数量"].quantile(0.25) 
c=data["数量"] 
c[(c>=(a-b)*1.5+a)|(c<=b-(a-b)*1.5)]=np.nan 
c.fillna(c.median(),inplace=True) 
print(c.describe()) 
2.采用标准差识别异常值
当数据服从正态分布时,异常值被定义为一组测定值中与平均值的偏差超过3倍标
准差的值。 
import numpy as np #导入NumPy 库
import pandas as pd #导入Pandas 库

59 
a=data["数量"].mean()+data["数量"].std()*3 
b=data["数量"].mean()-data["数量"].std()*3 
c=data["数量"] 
c[(c>=a)|(c<=b)]=np.nan 
c.fillna(c.median(),inplace=True) 
print(c.describe()) 
常用异常值处理方法如表3.2所示。
表3.2 常用异常值处理方法
方 法方法描述
删除 直接删除含有异常值的记录
视为缺失值利用缺失值处理方法填充
平均值修正用前后两个观测值的平均值修正异常值 
【例3.2】 通过z-score法判断异常值示例。 
import pandas as pd #导入Pandas 库
import matplotlib.pyplot as plt 
#构建包含异常值的矩阵
df=pd.DataFrame([[1, 12], [120, 17], [3, 31], [5, 53], [2, 22], [12, 32], [13, 43]], 
columns=['col1','col2']) 
print("数据为:\n",df) #打印输出
#散点图
plt.scatter(df['col1'],df['col2']) 
plt.show() 
#通过z-score 方法判断异常值,超过阈值为异常值
df_zscore=df.copy() #存储z-score 
cols=df.columns #获得数据框的列名
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 # 阈 值 为2.2,大于该值为True,否则为False 
print("异常值为:\n",df_zscore) # 打 印 输 出 
df_drop_outlier=df[df_zscore['col1']==False] #删除异常值所在的记录行
print("处理后的数据为:\n",df_drop_outlier) 
【程序运行结果】 
数据为: 
col1 col2 
0 1 12 
1 120 17 
2 3 31 
3 5 53 
4 2 22 
5 12 32 
6 13 43

60 
异常值为: 
col1 col2 
0 False False 
1 True False 
2 False False 
3 False False 
4 False False 
5 False False 
6 False False 
处理后的数据为: 
col1 col2 
0 1 12 
2 3 31 
3 5 53 
4 2 22 
5 12 32 
6 13 43 
程序运行结果如图3.1所示。
图3.1 例3.2程序运行结果
3.2.3 重复值
重复值的存在会影响数据分析的准确性。目前消除重复值的基本思想是排序和合
并。对数据进行排序后,比较邻近数据是否相似来检测数据是否重复。
消除重复数据的算法主要有优先队列算法、近邻排序法(sorted-neighborhood 
method)和多趟近邻排序法(multi-passsorted-neighborhoodmethod)。
3.2.4 Pandas数据清洗函数
Pandas提供了如下函数用于数据清洗和预处理:

61 
. df.duplicated:判断各行是否重复,False为非重复值。
. df.drop_duplicates:删除重复行。
. df.fillna(num):用实数num 填充缺失值。
. df.dropna:删除DataFrame数据中的缺失值,即删除NaN 数据。其语法为 
DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False) 
参数说明如表3.3所示。
表3.3 df.dropna函数的参数说明
参 数说 明
axis 0为行,1为列
how any表示删除带有NaN的行,all表示删除全为NaN的行
thresh 取值为int型,保留至少指定个非NaN行
subset 取值为list型,在特定列处理缺失值
inplace True表示修改原文件,False表示不修改原文件 
. deldf[c' ol1']:直接删除某列。
. df.drop([]c' ol1',…],axis=1):删除指定列,也可以删除指定行。
. df.rename(index={r' ow1':'A'},columns={c' ol1':B' '}):重命名索引名和列名。
. df.replace():替换DataFrame,可以用字典表示,例如{1' ':'A',2' :B' '}。
. df[].map(function):对指定列进行函数转换。map是Series中的函数。
. pd.merge(df1,df2,on=c' ol1',how=i'nner',sort=True):合并两个DataFrame, 
按照共有的列作内连接(交集),outer为外连接(并集),对结果排序。
. df1.combine_first(df2):用df2的数据补充df1的缺失值。
【例3.3】 重复值处理示例。 
import pandas as pd #导入Pandas 库
#生成异常数据
data1, data2, data3, data4=['a', 3], ['b', 2], ['a', 3], ['c', 2] 
df=pd.DataFrame([data1, data2, data3, data4], columns=['col1', 'col2']) 
print("数据为:\n",df) #打印输出
isDuplicated=df.duplicated() #判断重复数据记录
print("重复值为:\n",isDuplicated) #打 印 输 出 
print("删除数据记录中所有列值相同的记录:\n",df.drop_duplicates()) 
print("删除数据记录中col1 值相同的记录:\n",df.drop_duplicates(['col1'])) 
print("删除数据记录中col2 值相同的记录:\n",df.drop_duplicates(['col2'])) 
print("删除数据记录中指定列(col1/col2)值相同的记录:\n",df.drop_duplicates 
(['col1', 'col2']))

62 
【程序运行结果】 
数据为: 
col1 col2 
0 a 3 
1 b 2 
2 a 3 
3 c 2 
重复值为: 
0 False 
1 False 
2 True 
3 False 
dtype: bool 
删除数据记录中所有列值相同的记录: 
col1 col2 
0 a 3 
1 b 2 
3 c 2 
删除数据记录中col1 值相同的记录: 
col1 col2 
0 a 3 
1 b 2 
3 c 2 
删除数据记录中col2 值相同的记录: 
col1 col2 
0 a 3 
1 b 2 
删除数据记录中指定列(col1/col2)值相同的记录: 
col1 col2 
0 a 3 
1 b 2 
3 c 2 
【例3.4】 df.fillna(num)示例。 
from numpy import nan as NaN 
import pandas as pd 
df1=pd.DataFrame([[1,2,3],[NaN,NaN,2],[NaN,NaN,NaN],[8,8,NaN]]) 
print("df1:\n{}\n".format(df1)) 
df2=df1.fillna(100) 
print("df2:\n{}\n".format(df2)) 
【程序运行结果】 
df1:

63 
0 1 2 
0 1.0 2.0 3.0 
1 NaN NaN 2.0 
2 NaN NaN NaN 
3 8.0 8.0 NaN 
df2: 
0 1 2 
0 1.0 2.0 3.0 
1 100.0 100.0 2.0 
2 100.0 100.0 100.0 
3 8.0 8.0 100.0 
【例3.5】 df.dropna示例。 
from numpy import nan as NaN 
import pandas as pd 
df1=pd.DataFrame([[1,2,3],[NaN,NaN,2],[NaN,NaN,NaN],[8,8,NaN]]) 
print("df1:\n{}\n".format(df1)) 
df2=df1.dropna() 
print("df2:\n{}\n".format(df2)) 
【程序运行结果】 
df1: 
0 1 2 
0 1.0 2.0 3.0 
1 NaN NaN 2.0 
2 NaN NaN NaN 
3 8.0 8.0 NaN 
df2: 
0 1 2 
0 1.0 2.0 3.0 
【例3.6】 df.replace示例。 
import pandas as pd 
#创建数据集
df=pd.DataFrame( 
{ '名称':['产品1','产品2','产品3','产品4','产品5','产品6','产品7', 
'产品8'], 
'数量':['A','0.7','0.8','0.4','0.7','B','0.76','0.28'], 
'金额':['0','0.48','0.33','C','0.74','0','0','0.22'], 
'合计':['D','0.37','0.28','E','0.57','F','0','0.06'], } 
) 
#原DataFrame 并没有改变,改变的只是一个副本

64 
print("df:\n{}\n".format(df)) 
df1=df.replace('A', 0.1) 
print("df1:\n{}\n".format(df1)) 
#只需要替换某个数据的部分内容
df2=df['名称'].str.replace('产品', 'product') 
print("df2:\n{}\n".format(df2)) 
#如果要改变原数据,应添加常用参数inplace=True,用于替换部分区域
df['合计'].replace({'D':0.11111, 'F':0.22222}, inplace=True) 
print("df:\n{}\n".format(df)) 
【程序运行结果】 
df:
合计名称数量金额
0 D 产品1 A 0 
1 0.37 产品2 0.7 0.48 
2 0.28 产品3 0.8 0.33 
3 E 产品4 0.4 C 
4 0.57 产品5 0.7 0.74 
5 F 产品6 B 0 
6 0 产品7 0.76 0 
7 0.06 产品8 0.28 0.22 
df1:
合计名称数量金额
0 D 产品1 0.1 0 
1 0.37 产品2 0.7 0.48 
2 0.28 产品3 0.8 0.33 
3 E 产品4 0.4 C 
4 0.57 产品5 0.7 0.74 
5 F 产品6 B 0 
6 0 产品7 0.76 0 
7 0.06 产品8 0.28 0.22 
df2: 
0 product1 
1 product2 
2 product3 
3 product4 
4 product5 
5 product6 
6 product7 
7 product8 
Name: 名称, dtype: object

65 
df: 
合计名称数量金额
0 0.11111 产品1 A 0 
1 0.37 产品2 0.7 0.48 
2 0.28 产品3 0.8 0.33 
3 E 产品4 0.4 C 
4 0.57 产品5 0.7 0.74 
5 0.22222 产品6 B 0 
6 0 产品7 0.76 0 
7 0.06 产品8 0.28 0.22 
【例3.7】 df[].map示例。 
import pandas as pd 
import numpy as np 
df=pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'], 
'key2' : ['one', 'two', 'one', 'two', 'one'], 
'data1' : np.arange(5), 
'data2' : np.arange(5,10)}) 
print("df:\n{}\n".format(df)) 
df['data1']=df['data1'].map(lambda x : "%.3f"%x) 
print("df:\n{}\n".format(df)) 
【程序运行结果】 
df:
data1 data2 key1 key2 
0 0 5 a one 
1 1 6 a two 
2 2 7 b one 
3 3 8 b two 
4 4 9 a one 
df:
data1 data2 key1 key2 
0 0.000 5 a one 
1 1.000 6 a two 
2 2.000 7 b one 
3 3.000 8 b two 
4 4.000 9 a one 
【例3.8】 pd.merge(df1,df2)示例。 
import pandas as pd 
left=pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 
'A': ['A0', 'A1', 'A2', 'A3'], 
'B': ['B0', 'B1', 'B2', 'B3']})

66 
right=pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 
'C': ['C0', 'C1', 'C2', 'C3'], 
'D': ['D0', 'D1', 'D2', 'D3']}) 
result=pd.merge(left, right, on='key') 
#on 参数传递的key 作为连接键
print("left:\n{}\n".format(left)) 
print("right:\n{}\n".format(right)) 
print("merge:\n{}\n".format(result)) 
【程序运行结果】 
left:
A B key 
0 A0 B0 K0 
1 A1 B1 K1 
2 A2 B2 K2 
3 A3 B3 K3 
right: 
C D key 
0 C0 D0 K0 
1 C1 D1 K1 
2 C2 D2 K2 
3 C3 D3 K3 
merge: 
A B key C D 
0 A0 B0 K0 C0 D0 
1 A1 B1 K1 C1 D1 
2 A2 B2 K2 C2 D2 
3 A3 B3 K3 C3 D3 
【例3.9】 df1.combine_first(df2)示例。 
from numpy import nan as NaN 
import numpy as np 
import pandas as pd 
a=pd.Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],index=['f','e','d','c','b', 
'a']) 
b=pd.Series([1,np.nan,3,4,5,np.nan],index=['f','e','d','c','b','a']) 
print(a) 
print(b) 
c=b.combine_first(a) 
print(c)

67 
【程序运行结果】 
f NaN 
e 2.5 
d NaN 
c 3.5 
b 4.5 
a NaN 
dtype: float64 
f 1.0 
e NaN 
d 3.0 
c 4.0 
b 5.0 
a NaN 
dtype: float64 
f 1.0 
e 2.5 
d 3.0 
c 4.0 
b 5.0 
a NaN 
dtype: float64 
3.3 特征预处理
有一句话在业界广泛流传:“数据和特征决定了机器学习的上限,而模型和算法只是
逼近这个上限而已。”这里的数据是指经过特征预处理后的数据。特征预处理就是对数据
进行集成、转换、规约等一系列处理,使之适合算法模型的过程。
Sklearn提供了preprocessing模块,用于进行归一化、标准化、鲁棒化、正则化等数据
预处理。preprocessing模块常用方法如表3.4所示。
表3.4 preprocessing模块常用方法
方 法 名方法含义
preprocessing.MinMaxScaler 归一化
preprocessing.StandardScaler 标准化
preprocessing.RobustScaler 鲁棒化
preprocessing.normalize 正则化

68 
3.3.1 归一化
归一化又称为区间缩放法,是数据处理的必要工作。由于不同评价指标往往具有不
同的量纲,数值差别较大,从而影响数据分析的结果。为了让特征具有同等重要性,可以
采用归一化(MinMaxScaler)将不同规格的数据转换到同一个规格。归一化利用边界值
信息将特征的取值区间缩放到某个特点的范围,例如[0,1]等。
归一化计算公式如下: 
X'= x - min 
max-min 
X″=X'(mx-mi)+mi 
参数解释如下: 
. max:最大值。
. min:最小值。
. mx,mi:用于指定区间,默认mx为1,mi为0。
归一化将原始数据通过线性变换缩放到[0,1]。由于异常值往往是最大值或最小值, 
所以归一化的鲁棒性较差。
Sklearn提供了MinMaxScaler方法进行归一化,具体语法如下: 
MinMaxScaler(feature_range=(0,1)) 
参数feature_range=(0,1)将范围设置为0~1。
【例3.10】 归一化示例。
现有3个样本,每个样本有4个特征,如表3.5所示。
表3.5 样本特征
特征1 特征2 特征3 特征4 
90 2 10 40 
60 4 15 45 
75 3 13 46 
from sklearn.preprocessing import MinMaxScaler 
def Normalization(): #实例化一个转换器类 
Normalization=MinMaxScaler(feature_range=(0,1)) #范围设置为0~1 
data=[[90,2,10,40],[60,4,15,45],[75,3,13,46]] 
print(data) 
#调用fit_transform 
data_Normal=Normalization.fit_transform(data) 
print(data_Normal) 
return None 
if __name__=='__main__':

69 
Normalization() 
【程序运行结果】 
[[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]] 
[[1. 0. 0. 0. ] 
[0. 1. 1. 0.83333333 ] 
[0.5 0.5 0.6 1. ]] 
3.3.2 标准化
标准化(standardization)用于解决归一化容易受到样本中最大值或者最小值等异常
值的影响的问题,将数据按比例缩放到特定区间。
标准差公式如下: 
σ= 1 nΣN 
i=1 (xi -μ)2 
z-score标准化转换公式如下: 
z =x -μ 
σ 
标准化的前提是特征值服从正态分布。进行标准化后,数据聚集在0附近,方差为
1,有利于模型的训练。Sklearn提供了StandardScaler方法实现标准化,具体语法如下: 
StandardScaler(copy, with_mean) 
参数含义如下: 
.copy:取值为True或False。在用归一化的值替代原来的值时设置为False。
. with_mean:取值为True或False。在处理稀疏矩阵时设置为False。
【例3.11】 标准化示例。 
from sklearn.preprocessing import StandardScaler 
def Standardization(): 
'''标准化函数''' 
std=StandardScaler() 
data=[[1.,-1.,3.],[2.,4.,2.],[4.,6.,-1.]] 
print(data) 
data_Standard=std.fit_transform(data) 
print(data_Standard) 
return None 
if __name__=='__main__': 
Standardization() 
【程序运行结果】 
[[1.0, -1.0, 3.0], [2.0, 4.0, 2.0], [4.0, 6.0, -1.0]]

70 
[[-1.06904497 -1.35873244 0.98058068] 
[-0.26726124 0.33968311 0.39223227] 
[ 1.33630621 1.01904933 -1.37281295]] 
3.3.3 鲁棒化
当数据包含许多异常值时,使用平均值和方差缩放均不能取得较好效果,可以使用鲁
棒性缩放(RobustScaler)方法进行处理。
preprocessing模块的RobustScaler方法使用中位数和四分位数进行数据转换,直接
将异常值剔除,具体语法如下: 
RobustScaler(quantile_range, with_centering, with_scaling) 
参数含义如下: 
. with_centering:布尔值,默认值为True,表示在缩放之前将数据居中。
. with_scaling:布尔值,默认值为True,表示将数据缩放到四分位数范围。
. quantile_range:元组,默认值为(25.0,75.0),即IQR,表示用于计算scale_的分
位数范围。
【例3.12】 鲁棒化示例。 
from sklearn.preprocessing import RobustScaler 
X=[[ 1., -2., 2.],[ -2., 1., 3.],[ 4., 1., -2.]] 
transformer=RobustScaler().fit(X) 
RobustScaler(quantile_range=(25.0,75.0),with_centering= True,with_scaling= 
True) 
print(transformer.transform(X)) 
【程序运行结果】 
[[ 0. -2. 0. ] 
[-1. 0. 0.4] 
[ 1. 0. -1.6]] 
3.3.4 正则化
正则化(normalization)是将每个样本缩放到单位范式,使数据分布在一个半径为1 
的圆或者球内。preprocessing模块提供了normalize方法以实现正则化,具体语法如下: 
normalize(X, norm='l2') 
参数含义如下: 
. X:样本数据。
. norm=l'2' :L2范式。

71 
【例3.13】 正则化示例。 
from sklearn.preprocessing import normalize 
X=[[ 1., -1., 2.],[ 2., 0., 0.],[ 0., 1., -1.]] 
X_normalized=normalize(X, norm='l2') 
print(X_normalized) 
【程序运行结果】 
[[ 0.40824829 -0.40824829 0.81649658] 
[ 1. 0. 0. ] 
[ 0. 0.70710678 -0.70710678]] 
3.3.5 学生数据清洗示例
【例3.14】 学生数据清洗示例。
初始化并显示数据: 
import pandas as pd 
import numpy as np 
from collections import Counter 
from sklearn import preprocessing 
from matplotlib import pyplot as plt 
import seaborn as sns 
plt.rcParams['font.sans-serif']=['SimHei'] #中文字体设置为黑体
plt.rcParams['axes.unicode_minus']=False #解决保存图像时负号显示为方块的问题
sns.set(font='SimHei') #解决Seaborn 中文显示问题
data=pd.read_excel("d:/dummy.xls") #在D 盘根目录下创建dummy.xls 文件
print(data) 
【程序运行结果】 
姓名学历成绩能力学校
0 小红博士90.0 100.0 同济
1 小黄硕士90.0 89.0 交大
2 小绿本科80.0 98.0 同济
3 小白硕士90.0 99.0 复旦
4 小紫博士100.0 78.0 同济
5 小城本科80.0 98.0 交大
6 校的NaN NaN NaN NaN 
显示序列的前n 行(默认值): 
print("data head:\n",data.head())

72 
【程序运行结果】 
data head: 
姓名学历成绩能力学校
0 小红博士90.0 100.0 同济
1 小黄硕士90.0 89.0 交大
2 小绿本科80.0 98.0 同济
3 小白硕士90.0 99.0 复旦
4 小紫博士100.0 78.0 同济
查看数据的行列大小: 
print("data shape:\n",data.shape) 
【程序运行结果】 
data shape: 
(7, 5) 
显示指定列的数据描述属性值: 
print("data descibe:\n",data.describe()) 
【程序运行结果】 
data descibe: 
成绩能力
count 6.000000 6.000000 
mean 88.333333 93.666667 
std 7.527727 8.640988 
min 80.000000 78.000000 
25% 82.500000 91.250000 
50% 90.000000 98.000000 
75% 90.000000 98.750000 
max 100.000000 100.000000 
进行列级别的判断,只要某一列有NaN 或值为空,则为真: 
data.isnull().any() 
将列中为NaN 或值为空的个数统计出来,并将缺失值最多的排在前面: 
total=data.isnull().sum().sort_values(ascending=False) 
print("total:\n",total) 
【程序运行结果】 
total: 
学校 1 
能力 1 
成绩 1

73 
学历 1 
姓名 0 
输出百分比: 
percent=(data.isnull().sum()/data.isnull().count()).sort_values(ascending= 
False) 
missing_data=pd.concat([total, percent], axis=1, keys=['Total', 'Percent']) 
missing_data.head(20) 
导入missingno并删除缺失值: 
import missingno #missingno 用于可视化缺失值
missingno.matrix(data) 
data=data.dropna(thresh=data.shape[0]*0.5,axis=1) 
#将至少有一半以上是非空的列筛选出来 
#如果某一行都是NaN 才删除,默认只保留没有空值的行
data.dropna(axis=0,how='all') 
print(data) 
统计重复记录数: 
data.duplicated().sum() 
data.drop_duplicates() 
data.columns #对数据中的连续型字段和离散型字段进行归类
id_col=['姓名'] 
cat_col=['学历','学校'] # 离 散 型 无 序 
cont_col=['成绩','能力'] #数 值 型 
print (data[cat_col]) # 离 散 型 数 据 部分
print (data[cont_col]) # 连 续 型 数 据 部 分
计算出现的频次: 
for i in cat_col: 
print(pd.Series(data[i]).value_counts()) 
plt.plot(data[i]) 
对于离散型数据,对其获取哑变量: 
dummies=pd.get_dummies(data[cat_col]) 
print("哑变量:\n",dummies) 
【程序运行结果】 
哑变量: 
学历_博士学历_本科学历_硕士学校_交大学校_同济学校_复旦
0 1 0 0 0 1 0 
1 0 0 1 1 0 0 
2 0 1 0 0 1 0 
3 0 0 1 0 0 1 
4 1 0 0 0 1 0

74 
5 0 1 0 1 0 0 
6 0 0 0 0 0 0 
对连续型数据进行统计: 
data[cont_col].describe() 
对连续型数据,将偏度大于0.75的数值用取对数的方法进行转换,使之符合正态分布: 
skewed_feats=data[cont_col].apply(lambda x: (x.dropna()).skew() ) #计算偏度
skewed_feats=skewed_feats[skewed_feats>0.75] 
skewed_feats=skewed_feats.index 
data[skewed_feats]=np.log1p(data[skewed_feats]) 
#print(skewed_feats) 
对连续型数据进行标准化: 
scaled=preprocessing.scale(data[cont_col]) 
scaled=pd.DataFrame(scaled,columns=cont_col) 
print(scaled) 
m=dummies.join(scaled) 
data_cleaned=data[id_col].join(m) 
print("标准化:\n",data_cleaned) 
【程序运行结果】 
标准化: 
姓名学历_博士学历_本科学历_硕士学校_交大学校_同济学校_复旦成绩能力
0 小红1 0 0 0 1 0 0.242536 0.802897 
1 小黄0 0 1 1 0 0 0.242536 -0.591608 
2 小绿0 1 0 0 1 0 -1.212678 0.549350 
3 小白0 0 1 0 0 1 0.242536 0.676123 
4 小紫1 0 0 0 1 0 1.697749 -1.986112 
5 小城0 1 0 1 0 0 -1.212678 0.549350 
6 校的0 0 0 0 0 0 NaN NaN 
显示变量之间的相关性: 
print("变量之间的相关性:\n",data_cleaned.corr()) 
【程序运行结果】 
变量之间的相关性: 
学
历_博士
学历_本科
学历_硕士
学校_交大
学校_同济
学校_复旦
成绩
能力 
学历_博士
1.000000 
-0.400000 
-0.400000 
-0.400000 
0.730297 
-0.258199 
0.685994 
-0.418330 
学历_本科
-0.400000 
1.000000 
-0.400000 
0.300000 
0.091287 
-0.258199 
-0.857493 
0.388449 
学历_硕士
-0.400000 
-0.400000 
1.000000 
0.300000 
-0.547723 
0.645497 
0.171499 
0.029881 
学校_交大
-0.400000 
0.300000 
0.300000 
1.000000 
-0.547723 
-0.258199 
-0.342997 
-0.014940 
学校_同济
0.730297 
0.091287 
-0.547723 
-0.547723 
1.000000 
-0.353553 
0.242536 
-0.211289 
学校_复旦
-0.258199 
-0.258199 
0.645497 
-0.258199 
-0.353553 
1.000000 
0.108465 
0.302372

75 
成绩
0.685994 
-0.857493 
0.171499 
-0.342997 
0.242536 
0.108465 
1.000000 
-0.748177 
能力
-0.418330 
0.388449 
0.029881 
-0.014940 
-0.211289 
0.302372 
-0.748177 
1.000000 
绘制相关性的热力图: 
def corr_heat(df): 
dfData=abs(df.corr()) 
plt.subplots(figsize=(9, 9)) #设置画面大小 
sns.heatmap(dfData, annot=True, vmax=1, square=True, cmap="Blues") 
#plt.savefig('./BluesStateRelation.png') 
plt.show() 
corr_heat(data_cleaned) 
程序运行结果如图3.2所示。
图3.2 相关性的热力图