DW数据清洗及特征处理


数据清洗及特征处理可以让数据看起来规律性更强,为后面操作做铺垫。

我们拿到的数据通常是不干净的,所谓的不干净,就是数据中有缺失值,有一些异常点等,需要经过一定的处理才能继续做后面的分析或建模,所以拿到数据的第一步是进行数据清洗,本章我们将学习缺失值、重复值、字符串和数据转换等操作,将数据清洗成可以分析或建模的亚子。

1 缺失值观察与处理

我们拿到的数据经常会有很多缺失值,比如我们可以看到Cabin列存在NaN,那其他列还有没有缺失值,这些缺失值要怎么处理呢

1.1 任务一:缺失值观察
(1) 请查看每个特征缺失值个数
(2) 请查看Age, Cabin, Embarked列的数据
以上方式都有多种方式,所以大家多多益善

#方法一
df.info()
#方法二
df.isnull().sum()  #缺失值(为空)的个数
df.isna().sum() #缺失值的个数

输出一样

PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

1.2 任务二:对缺失值进行处理
(1)处理缺失值一般有几种思路

(2) 请尝试对Age列的数据的缺失值进行处理

(3) 请尝试使用不同的方法直接对整张表的缺失值进行处理

#处理缺失值的一般思路:
#提醒:可使用的函数有--->dropna函数与fillna函数
#将空值怎么变成了NaN
df[df['Age'] == np.nan] = 0
df.loc[5:7,'Age']
#df[df['Age']==None]=0
df.loc[5:7,'Age']
5     NaN
6    54.0
7     2.0
Name: Age, dtype: float64
#age 是有空值,不是NaN,所以用isnull
df[df['Age'].isnull()] = 0 # 这是将一整行变成了0 是不对的
df.loc[5:7]
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
5000000.00000.000000
6701McCarthy, Mr. Timothy Jmale54.0001746351.8625E46S
7803Palsson, Master. Gosta Leonardmale2.03134990921.0750NaNS

检索空缺值用np.nan要比用None好,数值列读取数据后,空缺值的数据类型为float64所以用None一般索引不到,比较的时候最好用np.nan

#正解
"""
·dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
axis=0按行删除,1按列
how:'any','all'
thresh要求保留的非NA值个数 eg.thresh=2 仅保留至少具有2个非NA值的行/列
subset=['列名1', '列名2']定义要在哪些列中查找缺失值
inplace=True/False 为True时对原数据进行永久性修改
例子:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html
"""
df.dropna(axis=0,how='any').head(3) #默认按行axis=0,方式any
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S
6701McCarthy, Mr. Timothy Jmale54.0001746351.8625E46S
"""
·fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
value缺失数据填充的值
method:ffill/bfill 将上一个有效观测向前传播到下一个缺失值里,也就是将缺失值前面的数填到缺失的地方(感觉是按列) 
limit=n:替换每一列的前n个NaN元素 
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html
"""
df.fillna(0).head()
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.25000S
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.92500S
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S
4503Allen, Mr. William Henrymale35.0003734508.05000S

2 重复值观察与处理

由于这样那样的原因,数据中会不会存在重复值呢,如果存在要怎样处理呢

df.duplicated() #查看是否有重复的行(两行所有列完全一样算重复)
#也可以对特定的列进行重复项判断
df.duplicated(['Age'])
#删除重复行
"""有一个keep参数
当keep=False时,就是去掉所有的重复行 
当keep=‘first’时,就是保留第一次出现的重复行 
当keep=’last’时就是保留最后一次出现的重复行。
"""
df.drop_duplicates().head(3)

3 特征观察与处理

我们对特征进行一下观察,可以把特征大概分为两大类:
数值型特征:Survived ,Pclass, Age ,SibSp, Parch, Fare,其中Survived, Pclass为离散型数值特征,Age,SibSp, Parch, Fare为连续型数值特征
文本型特征:Name, Sex, Cabin,Embarked, Ticket,其中Sex, Cabin, Embarked, Ticket为类别型文本特征

数值型特征一般可以直接用于模型的训练,但有时候为了模型的稳定性及鲁棒性会对连续变量进行离散化。
文本型特征往往需要转换成数值型特征才能用于建模分析。

3.1 任务一:对连续型特征(年龄)进行分箱(离散化)处理

#分箱操作是什么:
#将连续型变量分到不同箱子里成为离散型变量
#平均分箱成5个年龄段
#【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.cut.html
df['AgeBand'] = pd.cut(df['Age'], 5,labels = ['1','2','3','4','5'])
df.head(3)
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAgeBand
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS2
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C3
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS2
#划分为(0,5](5,15] (15,30] (30,50] (50,80]五个年龄段
df['AgeBand'] = pd.cut(df['Age'],[0,5,15,30,50,80],labels = ['1','2','3','4','5'])
df.head(3)
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAgeBand
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS3
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C4
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS3
#按10% 30% 50 70% 90%五个年龄段分箱
df['AgeBand'] = pd.qcut(df['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels = ['1','2','3','4','5'])  
#存疑
#【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.qcut.html
df.head(3)
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAgeBand
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS2
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C5
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS3

3.2 任务二:对文本型特征转换成数值型特征的方法

#(1) 查看类别文本变量名及种类
print(df['Sex'].value_counts())  #返回每个元素的值有多少 
print(df['Sex'].unique())   #返回所有唯一值
print(df['Sex'].nunique())  #返回唯一值的个数
male      577
female    314
Name: Sex, dtype: int64
['male' 'female']
2
#(2)将文本变量Sex, Cabin ,Embarked用数值变量12345表示 
#方法一: replace
df['Sex_num'] = df['Sex'].replace(['male','female'],[1,2])
df.head(3)

#方法二: map
df['Sex_num'] = df['Sex'].map({'male': 1, 'female': 2}) #map一个映射,没有映射的自变量会变成NaN
df.head(3)
#方法三: 使用sklearn.preprocessing的LabelEncoder
#存疑????????????????????
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))

df.head(3)
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedAgeBandSex_numCabin_labelEncodeTicket_labelEncode
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS210.00
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C521.01
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS320.02
# (3) 将文本变量Sex, Cabin, Embarked用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)
    
df.head(3)
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFare...Age_65.0Age_66.0Age_70.0Age_70.5Age_71.0Age_74.0Age_80.0Embarked_CEmbarked_QEmbarked_S
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500...0000000001
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833...0000000100
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250...0000000001

3 rows × 107 columns

3.3 任务三:从纯文本Name特征里提取出Titles的特征(所谓的Titles就是Mr,Miss,Mrs等)

df['Title'] = df.Name.str.extract('([A-Za-z]+)\.', expand=False) 
#.(点号)-匹配除'\ n'的任意字符
"""
expand=True不加的话,df1中将只有一列,其实就是一个series。
当然,可以直接将这列加到df中:df[['新列名']]直接将新的两列加入原先dataframe中"""
df.head(3)
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFare...Age_66.0Age_70.0Age_70.5Age_71.0Age_74.0Age_80.0Embarked_CEmbarked_QEmbarked_STitle
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500...000000001Mr
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833...000000100Mrs
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250...000000001Miss

3 rows × 108 columns

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值