二、数据预处理—数据清洗及特征处理
我们拿到的数据通常是不干净的,所谓的不干净,就是数据中有缺失值,有一些异常点等,需要经过一定的处理才能继续做后面的分析或建模,所以拿到数据的第一步是进行数据清洗,本章将学习缺失值、重复值、字符串和数据转换等操作,将数据清洗成可以分析或建模的样子。
1、缺失值观察、检索与处理
载入库与数据
1.1、观察:查看每一个特征缺失值的个数
#方法一
pd.info()
#方法二
df.isnull().sum()
1.2、检索
检索Age列的空值
#空间问题只展示到有null的一行
df['Age'].isnull().head(6)
(df['Age']==None).head(6)
(df['Age']== np.nan).head(6)
np.isnan(df['Age']).head(6)
.isnull() & np.isnan() & np.pan & None
从以上结果可以看出np.nan与None检索空值失效,为什么呢?
通过查找相关资料得到以下
1、is & ==
is 是比较对象标识符是否一致,即两个对象在内存中的地址是否一致
==是比较两个对象的值是否相等。
is&==对None都有效,但np.nan只能用is,是因为np.nan 应该是没有值的,所以不能值判断,只能用对象引用判断,而None有空值,所以也可以值判断。
[扩展]Python对None进行判断时用is而不是==
None表示一个空的对象,是Python中一个特殊常量,如果一个变量是None,那么它一定和None指向同一个内存地址。而空值是Python中一个特殊值,数据为空不代表是空对象。
尽管有时==None可以获取目标结果,但如果一个对象的__eq__()方法被重载,就有可能影响结果的判断。
但是运行结果依旧是False,故None不是==的原因,而np.nan是不可以用==进行判断的。
2、None
None的数据类型为NoneType。NoneType只有一个值None,不支持任何运算也没有任何内建方法。None和任何其他的数据类型比较永远返回False。
因为数据类型不一样,所以None无法检测出数据中的NaN值。
3、np.nan
数据类型为float,对空值进行判断只能用np.isnan()而不能用==np.nan。
np.nan自己都不能用==来判断
1.3、处理
处理缺失值基本的思路:
①直接使用含有缺失值的特征
②删除含有缺失值的特征:dropna
#dropna默认删除包含缺失值的行
df.dropna()
#删除所有值为NA的列
df.dropna(axis=1,how='all')
# how='all':删除所有值为NA的行
df.dropna(how='all')
#涉及时间序列数据,可以用thresh参数来保留包含一定数量的观察值的行
df.dropna(thresh=n)
#删除在'Age'列与'Sex'列中包含空缺值的行
df.dropna(subset=['Age','Sex'])
#与df.dropna()结果相同
df[df.notnull()]
DataFrame.dropna( axis=0, how=‘any’, thresh=None, subset=None, inplace=False)
1.axis确定删除包含缺失值的行还是列
axis=0or'index'(默认):行,axis=1or'columns':列
2.how='all’或者how=‘any’
how='any’(默认):删除只要含有缺失值的行(列)
how='all’:删除全是缺失值的行(列)
3.thresh=n 表示:保留下来的每一行,其非NA的数目大于等于n。
thresh=2表示保留下来的每一个数据行,其非NA值的数目最少是2。
4.subset:删除指定列中含有缺失值的行
5.inplace:是否在原数据上修改
inplace=False(默认)返回一个包含NaN值的副本;nplace=True在原数据上修改
③补全缺失值:fillna
#用常数填充
df.fillna(0)
#使用字典为不同列填入不同值.默认(axis=0)对列操作
df.fillna({'Age':0.5,6:0})
#插值方法:指定method参数填充
#用缺失值的前一个非缺失值去填充该缺失值
df.fillna(method='ffill')
#用缺失值的下一个非缺失值填充该缺失值
df.fillna(method='dfill')
#限定每列填充数量
df.fillna(method='ffill',limit=2)
DataFrame.fillna(value=None,method=None,axis=None,inplace=False,limit=None,donwncast=None)
1.value:要填充的常数
2.method
pad/ffill:用前一个非缺失值去填充该缺失值
backfill/bfill:用下一个非缺失值填充该缺失值
3.axis确定删除包含缺失值的行还是列
axis=0or'index'(默认):列,axis=1or'columns':行
4.inplace:是否在原数据上修改
inplace=False(默认)返回一个副本;nplace=True在原数据上修改
5.limit:限制填充个数
2、重复值观察与处理
2.1、观察:查看数据中的重复值
df[df.duplicated()]
2.2、处理:对重复值进行处理
df.drop_duplicated()
3、特征观察与处理
我们对特征进行一下观察,可以把特征大概分为两大类:
数值型特征:Survived ,Pclass, Age ,SibSp, Parch, Fare。 其中Survived, Pclass为离散型数值特征,Age,SibSp, Parch, Fare为连续型数值特征。
文本型特征:Name, Sex, Cabin,Embarked, Ticket,其中Sex, Cabin, Embarked, Ticket为类别型文本特征。
数值型特征一般可以直接用于模型的训练,但有时候为了模型的稳定性及鲁棒性会对连续变量进行离散化。文本型特征往往需要转换成数值型特征才能用于建模分析。
3.1、分箱(离散化)处理
什么是分箱操作?以及怎么实现分箱操作
分箱操作是一种数据的预处理操作,是为了减少观察误差的的一种做法。即将多个连续值分为数量较少的组。
Python中主要利用pd.cut和pd.qcut来实现分箱操作。pd.cut pd.qcut
pd.cut( x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise', )
1、x:要处理的数据(必须是一维的)。
2、bins:分组的依据,可以是整数,标量序列或者间隔索引。
整数:将x中的数据分成等宽的n份
标量序列:序列中的数值表示用来分档的分界值
间隔索引:“ bins”的间隔索引必须不重叠
3、right:指定那边是封闭的
right= True(默认):左开右闭; right=False:左闭右开
4、lables:可以通过向lables选项传递一个列表或数组来自定箱名
5、retbins:是否显示分箱的分界值
当bins取整数时可以设置retbins=True以显示分界值,得到划分后的区间
6、precision:整数,默认3,存储和显示分箱标签的精度。
pandas.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)
q:整数或分位数组成的数组。
#将连续变量Age平均分箱成5个年龄段,并分别用类别变量12345表示并保存
df['Age bins'] = pd.cut(df['Age'],5,labels = list(1,2,3,4,5))
df.to_csv('test_ave.csv')
#将连续变量Age划分为(0,5] (5,15] (15,30] (30,50] (50,80]五个年龄段,并分别用类别变量12345表示
bins=[0,5,15,30,50,80]
df['Age bins'] = pd.cut(df['Age'],bins,lables = list(1,2,3,4,5))
#或者
df['Age bins'] = pd.cut(df['Age'],[0,5,15,30,50,80],lables = list(1,2,3,4,5))
#保存
df.to_csv('test_cut.csv')
#将连续变量Age按10% 30% 50 70% 90%五个年龄段,并用分类变量12345表示
df['Age bins'] = pd.qcut(df['Age'],[0,0.1,0.3,0.5,0.7,0.9],lables = list(1,2,3,4,5))
df.to_csv('test_pr.cvs')
3.2、对文本变量进行转换
3.2.1 查看文本变量名及种类
.value_counts() & .unique()
#'Cabin'查询结果过多已隐藏
3.2.2、将文本变量Sex, Cabin ,Embarked用数值变量12345表示
.replace() & map.() & sklearn.preprocessing的LabelEncoder
①.replace()
#inplace = True直接在原数据上进行更改
②map.()
#.map()没有‘inplace’参数,那么可以在原表格新增一列作为参照。
③sklearn.preprocessing的LabelEncoder
#需要转换类型的数据要么是str要么是int,不可以二者兼有。Cabin原数据中有NaN,所以应当先将NaN转换成str类型(.astype())。
*利用for循环,批量操作
①sklearn.preprocessing的LabelEncoder
②map.()
3.2.3、将文本变量Sex, Cabin, Embarked用one-hot编码表示
什么是one-hot编码?为什么使用one-hot编码?怎样将数据转换成one-hot编码?......
利用pd.get_dummies()将离散的、无需的特征数字化。get_dummies只能处理字符串类别变量
pd.get_dummies(data, prefix=None, prefix_sep=’_’, dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)
1、data:需要处理的数据
array-like, Series, or DataFrame
2、prefix:指明列名前缀
3、prefix_sep=’_’:列名与前缀默认的连接符
......
将文本变量Sex用one-hot编码表示
利用for循环批量转换称one-hot编码
3.3、从纯文本Name特征里提取出Titles的特征(所谓的Titles就是Mr,Miss,Mrs等)
.str.extract(pat,flags=0,expand=True)
1、pag:正则表达式,需要提取的数据有什么规律
2、expand
默认为True.如果为真,则返回每个捕获组有一列的数据框。如果为假,如果有一个捕获组,则返回序列/索引;如果有捕获组,则返回数据框。