【回顾&简介在前一章的内容中,我们可以感觉到我们主要梳理基础知识,让您了解一些数据分析操作,主要从数据的各个角度进行观察。在这里,我们主要从事数据分析的过程学习,主要包括数据清理、数据特征处理、数据重构和数据可视化。这些内容为数据分析的最终建模和模型评价铺平了道路。
开始前,导入numpy、pandas包和数据
import numpy as np import pandas as pd df_train=pd.read_csv('train.csv')
2 第二章:数据清洗和特征处理
我们得到的数据通常是不干净的。所谓不干净,就是数据中有缺失值和一些异常点,需要经过一定的处理才能继续进行后续的分析或建模。因此,获取数据的第一步是清理数据。在本章中,我们将学习缺失值、重复值、字符串和数据转换,并将数据清理成可以分析或建模的子。
2.1 观察和处理缺失值
我们经常得到很多缺失值的数据,例如,我们可以看到Cabin列存在NaN,其他列是否有缺失值,如何处理这些缺失值?
2.1.1 任务一:观察缺失值
(1) 请检查每个特征的缺失值 (2) 请查看Age, Cabin, Embarked列的数据 以上方法有很多种,大家越多越好
df_train.isnull().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 df_train[['Age','Cabin','Embarked']]
| Age | Cabin | Embarked | |
|---|---|---|---|
| 0 | 22.0 | NaN | S |
| 1 | 38.0 | C85 | C |
| 2 | 26.0 | NaN | S |
| 3 | 35.0 | C123 | S |
| 4 | 35.0 | NaN | S |
| ... | ... | ... | ... |
| 886 | 27.0 | NaN | S |
| 887 | 19.0 | B42 | S |
| 888 | NaN | NaN | S |
| 889 | 26.0 | C148 | C |
| 890 | 32.0 | NaN | Q |
891 rows × 3 columns
2.1.2 任务二:处理缺失值
(1)处理缺失值一般有几种想法
(2) 请尝试对Age列的数据的缺失值进行处理
(3) 请尝试使用不同的方法直接处理整个表的缺失值
#处理缺失值的一般思路: #提醒:可用函数有—>dropna函数与fillna函数
dropna() fillna() # dropna 有用 df_train[df_train['Age'].isnull()]=0 df_train.isnull().sum() PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 529
Embarked 2
dtype: int64
# None 没用
df_train[df_train['Age']==None]=0
df_train.isnull().sum()
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 0
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 529
Embarked 2
dtype: int64
Cabin缺失值占了三分之二没必要讨论了
df_train=df_train.drop(['Cabin'],axis=1)
【思考1】dropna和fillna有哪些参数,分别如何使用呢?
【思考】检索空缺值用np.nan,None以及.isnull()哪个更好,这是为什么?如果其中某个方式无法找到缺失值,原因又是为什么?
【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html
【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html
2.2 重复值观察与处理
由于这样那样的原因,数据中会不会存在重复值呢,如果存在要怎样处理呢
2.2.1 任务一:请查看数据中的重复值
df_train.duplicated().sum()
176
2.2.2 任务二:对重复值进行处理
(1)重复值有哪些处理方式呢?
(2)处理我们数据的重复值
方法多多益善
df_train=df_train.drop_duplicates()
df_train.describe()
| PassengerId | Survived | Pclass | Age | SibSp | Parch | Fare | |
|---|---|---|---|---|---|---|---|
| count | 715.000000 | 715.000000 | 715.000000 | 715.00000 | 715.000000 | 715.000000 | 715.000000 |
| mean | 447.955245 | 0.405594 | 2.233566 | 29.65758 | 0.511888 | 0.430769 | 34.645990 |
| std | 259.480877 | 0.491350 | 0.841829 | 14.55875 | 0.929330 | 0.852844 | 52.897774 |
| min | 0.000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0.000000 |
| 25% | 221.500000 | 0.000000 | 1.000000 | 20.00000 | 0.000000 | 0.000000 | 8.050000 |
| 50% | 444.000000 | 0.000000 | 2.000000 | 28.00000 | 0.000000 | 0.000000 | 15.741700 |
| 75% | 677.500000 | 1.000000 | 3.000000 | 38.00000 | 1.000000 | 1.000000 | 33.250000 |
| max | 891.000000 | 1.000000 | 3.000000 | 80.00000 | 5.000000 | 6.000000 | 512.329200 |
2.2.3 任务三:将前面清洗的数据保存为csv格式
df_train.to_csv('cleaned_train.csv')
2.3 特征观察与处理
我们对特征进行一下观察,可以把特征大概分为两大类: 数值型特征:Survived ,Pclass, Age ,SibSp, Parch, Fare,其中Survived, Pclass为离散型数值特征,Age,SibSp, Parch, Fare为连续型数值特征 文本型特征:Name, Sex, Cabin,Embarked, Ticket,其中Sex, Cabin, Embarked, Ticket为类别型文本特征,数值型特征一般可以直接用于模型的训练,但有时候为了模型的稳定性及鲁棒性会对连续变量进行离散化。文本型特征往往需要转换成数值型特征才能用于建模分析。
2.3.1 任务一:对年龄进行分箱(离散化)处理
(1) 分箱操作是什么?
(2) 将连续变量Age平均分箱成5个年龄段,并分别用类别变量12345表示
(3) 将连续变量Age划分为[0,5) [5,15) [15,30) [30,50) [50,80)五个年龄段,并分别用类别变量12345表示
(4) 将连续变量Age按10% 30% 50% 70% 90%五个年龄段,并用分类变量12345表示
(5) 将上面的获得的数据分别进行保存,保存为csv格式 #分箱操作是什么: 对连续变量的操作,进行分组
bins_1 = [0,5,15,30,50,80]
df_train['Age_cat']= pd.cut(df_train['Age'],bins=bins_1,right=False,labels=[1,2,3,4,5])
df_train['Age'].describe()
count 715.00000
mean 29.65758
std 14.55875
min 0.00000
25% 20.00000
50% 28.00000
75% 38.00000
max 80.00000
Name: Age, dtype: float64
df_train['Age_cat1']=df_train['Age_rank']=pd.qcut(df_train['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels=[1,2,3,4,5])
df_train['Age_cat1']
0 2
1 5
2 3
3 4
4 4
..
885 5
886 3
887 2
889 3
890 4
Name: Age_cat1, Length: 715, dtype: category
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
df_train.to_csv('cleaned_train.csv')
【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.cut.html
【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.qcut.html
2.3.2 任务二:对文本变量进行转换
(1) 查看文本变量名及种类 (2) 将文本变量Sex, Cabin,Embarked用数值变量12345表示 (3) 将文本变量Sex, Cabin, Embarked用one-hot编码表示
注释:这里加入Cabin不合适,能分成n类,根据前缀去分类比较合适一些,后续作为学习延伸
df_train['Embarked'].unique(),df_train['Sex'].unique()
(array(['S', 'C', 0, 'Q', nan], dtype=object),
array(['male', 'female', 0], dtype=object))
# 方法一 :map
Sex_dict = {
'male':1,'female':2}
Embarked_dict={
'S':1,'C':2,'Q':3,'NaN':4}
df_train['Sex_num']=df_train['Sex'].map(Sex_dict)
df_train['Embarked_num']=df_train['Embarked'].map(Embarked_dict)
df_train.head(2)
| PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | Age_cat | Age_cat1 | Age_rank | Sex_num | Embarked_num | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S | 3 | 2 | 2 | 1.0 | 1.0 |
| 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C | 4 | 5 | 5 | 2.0 | 2.0 |
#方法二:拆分理解
ddf= pd.DataFrame({
'A':['A10','A22','A36','A4'],'B':['B56','B2','B578','B777']})
ddf
| A | B | |
|---|---|---|
| 0 | A10 | B56 |
| 1 | A22 | B2 |
| 2 | A36 | B578 |
| 3 | A4 | B777 |
for i in ['A','B']:
lbl=LabelEncoder()
label_dict1 = dict(zip(ddf[i].unique(),range(ddf[i].nunique())))
ddf[i+"_labelEncode"] = ddf[i].map(label_dict1)
ddf[i+"_labelEncode"] = lbl.fit_transform(ddf[i].astype(str))
print(label_dict1)
{'A10': 0, 'A22': 1, 'A36': 2, 'A4': 3}
{'B56': 0, 'B2': 1, 'B578': 2, 'B777': 3}
df_train['Cabin'].head(3),df_train['Ticket'].head(3),
(0 NaN
1 C85
2 NaN
Name: Cabin, dtype: object,
0 A/5 21171
1 PC 17599
2 STON/O2. 3101282
Name: Ticket, dtype: object)
#方法二: 使用sklearn.preprocessing的LabelEncoder
from sklearn.preprocessing import LabelEncoder
for feat in ['Cabin', 'Ticket']:
lbl = LabelEncoder() # 调用LE
label_dict = dict(zip(df_train[feat].unique(), range(df_train[feat].nunique())))
df_train[feat + "_labelEncode"] = df_train[feat].map(label_dict)
df_train[feat + "_labelEncode"] = lbl.fit_transform(df_train[feat].astype(str))
df_train.head(2)
| PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | Age_cat | Age_cat1 | Age_rank | Sex_num | Embarked_num | Cabin_labelEncode | Ticket_labelEncode | Title | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S | 3 | 2 | 2 | 1.0 | 1.0 | 135 | 409 | Mr |
| 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C | 4 | 5 | 5 | 2.0 | 2.0 | 74 | 472 | Mrs |
#方法三:one-hot编码
a=pd.get_dummies(df_train['Sex'],prefix='Onehot')
b=pd.get_dummies(df_train['Embarked'],prefix='Onehot')
df_train = pd.concat([df_train,a,b],axis=1)
df_train.head(2)
| PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | ... | Onehot_C | Onehot_Q | Onehot_S | Onehot_0 | Onehot_female | Onehot_male | Onehot_0 | Onehot_C | Onehot_Q | Onehot_S | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | ... | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
| 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | ... | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
2 rows × 33 columns
2.3.3 任务三:从纯文本Name特征里提取出Titles的特征(所谓的Titles就是Mr,Miss,Mrs等) 正则表达式
df_train['Title'] = df_train['Name'].str.extract('([A-Za-z]+)\.',expand=False) #expand=True就返回dataframe了 其实没搞懂 要再看看
df_train.head(1)
| PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | Age_cat | Age_cat1 | Age_rank | Sex_num | Embarked_num | Cabin_labelEncode | Ticket_labelEncode | Title | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.25 | NaN | S | 3 | 2 | 2 | 1.0 | 1.0 | 135 | 409 | Mr |
df_train.to_csv('cleaned_train.csv')