数据清洗及特征处理
1 数据清洗
1.1 加载数据
import numpy as np
import pandas as pd
df=pd.read_csv('train.csv')
1.2 缺失值的观察和处理
# 查看每个特征缺失值的个数
# 显示的是不含缺失值的个数
df.count()
df.info()
# 显示的是缺失值的个数
df.isnull().sum()
# 查看‘Age’,‘Cabin’,‘Embarked’列的数据
# 法一
df[['Age','Cabin','Embarked']]
# 法二
df.loc[:,['Age','Cabin','Embarked']].head(3)
# 法三
print(df.iloc[:,[5,10,11]].head(3))
处理缺失值的思路
1.删除缺失值
2.填充缺失值
#处理‘Age’列数据的缺失值
#令‘Age’列的缺失值为0
#法一
df[df['Age']==None]=0
#法二
df[df['Age].isnull()]=0
#法三
df[df['Age']==np.nan]=0
思考:检索空缺值用np.nan,None以及.isnull()哪个更好?
回答:数值列读取数据后,空缺值的数据类型为float64,所以None一般索引不到,比较的时候最好用np.nan。
#直接对整张表的缺失值进行处理
#删除含缺失值的列
df.dropna()
#用0填充缺失值
df.fillna(0)
思考:dropna和fillna()有哪些参数,分别如何使用?
回答:
参数名称(drop) | 说明 |
axis | axis=0删除行,axis=1删除列 |
how | any表示行或列有一个缺失值就清除 all表示要是整行都是缺失值才清除 |
thresh | 只接受一个int值 表示保留n个非空值的行或列 |
subset | 接受一个集合(可以使列表、元组、数组) 表示哪些列或行必须不能有空值,处在这些列或行的空值的行或列将被清除 |
inplace | 接受bool 如果为True,返回None并且直接对原数组进行缺失值的清理。 如果是False,那么只返回一个copy |
参数说明(fillna) | 说明 |
axis | axis=0,表示选择行 axis=1,表示选择列(默认) |
value | 用来表示代替缺失值的值 |
method | 取值为backfill(bfill)表示使用缺失值的下一个非缺失值来填补缺失值 取值为pad(ffil)表示使用缺失值的上一个非缺失值来填补缺失值 |
limit | 接受int 表示在每行或每列填补缺失值个数上限,超过这个上限不再继续填补。 |
inplace | 接受bool 如果为True,在原表上操作 如果是False,那么只返回一个copy |
1.3 重复值的观察与处理
#查看数据中的重复值
df[df.duplicated()]
#删除数据中的重复值(不改变原本数值)
df=df.drop_duplicates()
#如果想要保留最后一行或全部删除,用keep设置参数
df=df.drop_duplicates(keep='last')
df=df.drop_duplicates(keep=False)
#同样可以设置subset方法,就可以指定哪些字段重复视为重复值
df.drop_duplicates(subset=['Age','Sex'])
1.4 将清洗数据保存
df.to_csv('test_clear.csv')
2.特征观察与处理
特征大概可以分为2类
数值型特征 | 文本型特征 |
survived,pclass(离散型数值特征) Age,SlibSp,Parch,Fare(连续型数值特征) | Name Sex,Cabin,Embarked,Ticket(类别型文本特征) |
数值型特征一般可以直接用于模型的训练,但有时为了模型的稳定性以及鲁棒性会连续变量进行离散化。文本型特征往往需要转换成数值型特征才能用于建模分析。
2.1 分箱(离散化处理)
2.1.1 分箱操作是什么?
我们在建立模型前,一般需要对特征变量进行离散化,特征离散化后,模型会更稳定,降低模型过拟合的风险。尤其是采用 logsitic 建立评分卡模型时,必须对连续变量进行离散化。而特征离散化处理通常采用的就是分箱法,数据分箱(也称为离散分箱或分段)是一种数据预处理技术,用于减少次要观察误差的影响,提高泛化性。
数据分箱又分为有监督分箱和无监督分箱,是否使用标签进行离散化(分箱)决定了有监督还是无监督的离散化方法。
2.1.2 分箱操作实例
#平均分箱5个年龄段,并用类别变量1,2,3,4,5
df['AgeBand']=pd.cut(df['Age'],5,labels=[1,2,3,4,5])
#划分为(0,5],(5,15]...5个年龄段。
df['AgeBand']=pd.cut(df['Age'],[0,5,15,30,50,80],5,labels=[1,2,3,4,5])
#按10%,30%,...五个年龄段
df['AgeBand'] = pd.qcut(df['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels = [1,2,3,4,5])
2.2 对文本变量进行转换
2.2.1 查看文本变量名以种类
#查看文本变量名
#方法一 value_counts
df['Sex'].value_counts()
#方法二: unique
df['Sex'].unique()
#查看文本种类数量
df['Sex'].nunique()
2.2.2 用数值变量表示文本变量
#将类别文本转换为12345
#方法1 replace
df['Sex_num']=df['Sex'].replace(['male','female'],[1,2])
#方法2 map
df['Sex_num']=df['Sex'].map({'male':1,'female':2})
#方法三: 使用sklearn.preprocessing的LabelEncoder
#标准化标签,将标签值统一转换成range(标签值个数-1)范围内
from sklearn.preprocessing import LabelEncoder
for feat in ['Cabin', 'Ticket']:
lbl = LabelEncoder()
label_dict = dict(zip(df[feat].unique(), range(df[feat].nunique())))
df[feat + "_labelEncode"] = df[feat].map(label_dict)
df[feat + "_labelEncode"] = lbl.fit_transform(df[feat].astype(str))
2.2.3 将文本变量用one-hot 编码表示
#方法: OneHotEncoder
for feat in ["Age", "Embarked"]:
# x = pd.get_dummies(df["Age"] // 6)
# x = pd.get_dummies(pd.cut(df['Age'],5))
x = pd.get_dummies(df[feat], prefix=feat)
df = pd.concat([df, x], axis=1)
#df[feat] = pd.get_dummies(df[feat], prefix=feat)
2.2.4从纯文本Name特征里提取出Title的特征
#为了提取Mr,可以看到Mr前面有空格,且从大写字母开始再到小写字母 。
#所以该正则表达式也是类似:先空了一格,从大写字母A-Z中匹配,再从小写字母a-z中匹配, 到 .(点)这##里结束。
#\表示转义,在正则表达式中点(.)表示:匹配除换行符 \n 之外的任何单字符。若要直接使用则需要加上转#义符号
#expand= 布尔值,默认为真。 如果为真,则返回每个捕获组有一列的数据框。如果为假,如果有一个捕获 #组,则返回序列/索引;如果有捕获组,则返回数据框。
df['Title'] = df.Name.str.extract(' ([A-Za-z]+)\.', expand=False)