本文源自DataWhale在Github分享的教程,感谢大佬们的无私奉献。附上此项目主页。
GitHub-DataWhale

1 读取数据

1.1 导入库

import numpy as np
import pandas as pd

1.2读取数据

数据下载地址
(百度网盘:提取码:1234)

1.2.1读取train.csv并将列索引改为中文

data = pd.read_csv('data/train.csv')
data.columns = (['乘客ID',
                 '是否幸存',
                 '乘客等级',
                 '乘客姓名',
                 '性别',
                 '年龄',
                 '兄妹个数',
                 '父母小孩个数',
                 '船票信息',
                 '票价',
                 '客舱',
                 '登船港口'])
data.head()
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

1.2.2 查看列索引信息

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   乘客ID    891 non-null    int64  
 1   是否幸存    891 non-null    int64  
 2   乘客等级    891 non-null    int64  
 3   乘客姓名    891 non-null    object 
 4   性别      891 non-null    object 
 5   年龄      714 non-null    float64
 6   兄妹个数    891 non-null    int64  
 7   父母小孩个数  891 non-null    int64  
 8   船票信息    891 non-null    object 
 9   票价      891 non-null    float64
 10  客舱      204 non-null    object 
 11  登船港口    889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB

1.2.3 读取test.csv

test_1 = pd.read_csv('data/test.csv')
test_1.head()
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q
3 895 3 Wirz, Mr. Albert male 27.0 0 0 315154 8.6625 NaN S
4 896 3 Hirvonen, Mrs. Alexander (Helga E Lindqvist) female 22.0 1 1 3101298 12.2875 NaN S
test_1.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 11 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  418 non-null    int64  
 1   Pclass       418 non-null    int64  
 2   Name         418 non-null    object 
 3   Sex          418 non-null    object 
 4   Age          332 non-null    float64
 5   SibSp        418 non-null    int64  
 6   Parch        418 non-null    int64  
 7   Ticket       418 non-null    object 
 8   Fare         417 non-null    float64
 9   Cabin        91 non-null     object 
 10  Embarked     418 non-null    object 
dtypes: float64(2), int64(4), object(5)
memory usage: 36.0+ KB

2 数据分析/处理

2.1 对船票和年龄降序排列

data = data.sort_values(by=['票价','年龄'], ascending=False)
data.head(5)
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C
438 439 0 1 Fortune, Mr. Mark male 64.0 1 4 19950 263.0000 C23 C25 C27 S
341 342 1 1 Fortune, Miss. Alice Elizabeth female 24.0 3 2 19950 263.0000 C23 C25 C27 S
data.tail(5)
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口
481 482 0 2 Frost, Mr. Anthony Wood "Archie" male NaN 0 0 239854 0.0 NaN S
633 634 0 1 Parr, Mr. William Henry Marsh male NaN 0 0 112052 0.0 NaN S
674 675 0 2 Watson, Mr. Ennis Hastings male NaN 0 0 239856 0.0 NaN S
732 733 0 2 Knight, Mr. Robert J male NaN 0 0 239855 0.0 NaN S
815 816 0 1 Fry, Mr. Richard male NaN 0 0 112058 0.0 B102 S

1 发现票价越高,幸存的人数越多,前20人中,70%的人幸存;后20人中仅有一人幸存;

2 概率可能会较其他参数同水平的人更低。

2.2 观察船票/性别/年龄

①票价

data['票价'].describe()
count    891.000000
mean      32.204208
std       49.693429
min        0.000000
25%        7.910400
50%       14.454200
75%       31.000000
max      512.329200
Name: 票价, dtype: float64

②性别

data['性别'].describe()
count      891
unique       2
top       male
freq       577
Name: 性别, dtype: object

③年龄

data['年龄'].describe()
count    714.000000
mean      29.699118
std       14.526497
min        0.420000
25%       20.125000
50%       28.000000
75%       38.000000
max       80.000000
Name: 年龄, dtype: float64

总结

1.票价整体很低,仅有少数高价票

2.男性较女性更多,占64%

3.乘客年龄不高,28岁以下占50%,38岁以下占75%,有少数高龄乘客

3 数据清洗及特征处理

数据清洗简述

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

3.1 缺失值的观察与处理

3.1.1 缺失值观察

data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 891 entries, 679 to 815
Data columns (total 12 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   乘客ID    891 non-null    int64  
 1   是否幸存    891 non-null    int64  
 2   乘客等级    891 non-null    int64  
 3   乘客姓名    891 non-null    object 
 4   性别      891 non-null    object 
 5   年龄      714 non-null    float64
 6   兄妹个数    891 non-null    int64  
 7   父母小孩个数  891 non-null    int64  
 8   船票信息    891 non-null    object 
 9   票价      891 non-null    float64
 10  客舱      204 non-null    object 
 11  登船港口    889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 90.5+ KB
或者使用df.isnull().sum()
data.isnull().sum()
乘客ID        0
是否幸存        0
乘客等级        0
乘客姓名        0
性别          0
年龄        177
兄妹个数        0
父母小孩个数      0
船票信息        0
票价          0
客舱        687
登船港口        2
dtype: int64

3.1.2 缺失值的处理

过滤缺失值

①df.isnull 加 布尔索引,手动过滤缺失值

#  方法一
# data[data['年龄'].isnull()] = 0

②df.dropna方法

DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

# 方法二
# data.dropna()

补全缺失值

df.fillna() 方法

DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)

# data[data['年龄']].fillna()

3.2 重复值的观察与处理

3.2.1 观察重复值

data[data.duplicated()]
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口
data.duplicated().sum()
0

3.2.2 删除重复值

data.drop_duplicates()
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C
438 439 0 1 Fortune, Mr. Mark male 64.0 1 4 19950 263.0000 C23 C25 C27 S
341 342 1 1 Fortune, Miss. Alice Elizabeth female 24.0 3 2 19950 263.0000 C23 C25 C27 S
... ... ... ... ... ... ... ... ... ... ... ... ...
481 482 0 2 Frost, Mr. Anthony Wood "Archie" male NaN 0 0 239854 0.0000 NaN S
633 634 0 1 Parr, Mr. William Henry Marsh male NaN 0 0 112052 0.0000 NaN S
674 675 0 2 Watson, Mr. Ennis Hastings male NaN 0 0 239856 0.0000 NaN S
732 733 0 2 Knight, Mr. Robert J male NaN 0 0 239855 0.0000 NaN S
815 816 0 1 Fry, Mr. Richard male NaN 0 0 112058 0.0000 B102 S

891 rows × 12 columns

3.3 特征观察与处理

数值型特征:Survived ,Pclass, Age ,SibSp, Parch, Fare,其中Survived, Pclass为离散型数值特征,Age,SibSp, Parch, Fare为连续型数值特征

文本型特征:Name, Sex, Cabin,Embarked, Ticket,其中Sex, Cabin, Embarked, Ticket为类别型文本特征。

文本型特征往往需要转换成数值型特征才能用于建模分析。

3.3.1 对年龄进行分箱(离散化)处理

什么是分箱?

即连续值的离散化,把一组数据切分为若干“箱子”。

pd.cut方法详解

①将连续变量Age平均分箱成5个年龄段,并分别用类别变量12345表示

bins = 5 #bins为分组方法,可以为int、标量序列
data['年龄(离散化)'] = pd.cut(data['年龄'], bins, labels=['1','2','3','4','5'])
data.head(5)
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口 年龄(离散化)
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C 3
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C 3
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C 3
438 439 0 1 Fortune, Mr. Mark male 64.0 1 4 19950 263.0000 C23 C25 C27 S 4
341 342 1 1 Fortune, Miss. Alice Elizabeth female 24.0 3 2 19950 263.0000 C23 C25 C27 S 2

②将连续变量Age划分为[0,5) [5,15) [15,30) [30,50) [50,80)五个年龄段,并分别用类别变量12345表示

bins = [0,5,15,30,50,80]
data['年龄(离散化)'] = pd.cut(data['年龄'], bins, labels=['1','2','3','4','5'])
data.head()
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口 年龄(离散化)
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C 4
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C 4
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C 4
438 439 0 1 Fortune, Mr. Mark male 64.0 1 4 19950 263.0000 C23 C25 C27 S 5
341 342 1 1 Fortune, Miss. Alice Elizabeth female 24.0 3 2 19950 263.0000 C23 C25 C27 S 3

③将连续变量Age按10% 30% 50 70% 90%五个年龄段,并用分类变量12345表示

pd.qcut()方法详解

q = [0,0.1,0.3,0.5,0.7,0.9]
data['年龄(离散化)'] = pd.qcut(data['年龄'], q, labels=['1','2','3','4','5'])
data.head()
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口 年龄(离散化)
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C 4
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C 4
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C 4
438 439 0 1 Fortune, Mr. Mark male 64.0 1 4 19950 263.0000 C23 C25 C27 S NaN
341 342 1 1 Fortune, Miss. Alice Elizabeth female 24.0 3 2 19950 263.0000 C23 C25 C27 S 3

3.3.2 对文本变量进行转换

①查看文本变量名及种类(性别/客舱/登船港口)
方法一:value_counts
data['性别'].value_counts()
male      577
female    314
Name: 性别, dtype: int64
data['登船港口'].value_counts()
S    644
C    168
Q     77
Name: 登船港口, dtype: int64
方法二:unique()
data['客舱'].unique()
array(['B51 B53 B55', nan, 'B101', 'C23 C25 C27', 'B57 B59 B63 B66',
       'B58 B60', 'C45', 'C62 C64', 'C95', 'C82', 'B3', 'B5', 'C7',
       'C125', 'C91', 'C22 C26', 'B80', 'B78', 'C32', 'C99', 'E40', 'E34',
       'B96 B98', 'D48', 'D36', 'C68', 'C70', 'C65', 'C86', 'B69', 'B73',
       'B49', 'C78', 'C93', 'C92', 'B77', 'B79', 'C83', 'C50', 'E49',
       'C54', 'A34', 'B28', 'E67', 'E68', 'B41', 'B82 B84', 'B86', 'C46',
       'D20', 'D7', 'D11', 'D9', 'D26', 'D33', 'D49', 'D15', 'D37', 'C85',
       'B22', 'B35', 'C2', 'D10 D12', 'B30', 'E31', 'B18', 'B20', 'A20',
       'E36', 'E44', 'E50', 'E33', 'C123', 'E8', 'D30', 'D35', 'D19',
       'C126', 'C110', 'B71', 'A14', 'E46', 'D21', 'C101', 'A24', 'A32',
       'C90', 'B39', 'A10', 'A16', 'D28', 'F4', 'E63', 'A26', 'T', 'A6',
       'C52', 'C128', 'A5', 'D46', 'B19', 'D50', 'A31', 'A7', 'C30',
       'C104', 'B50', 'C106', 'A23', 'D6', 'C148', 'B42', 'D45', 'B37',
       'C118', 'C47', 'C49', 'C124', 'C111', 'B4', 'E38', 'C87', 'C103',
       'E17', 'E12', 'B38', 'E25', 'E24', 'D47', 'F2', 'A19', 'D17',
       'E58', 'F E69', 'G6', 'D', 'D56', 'E101', 'F33', 'E121', 'E77',
       'E10', 'F38', 'F G63', 'F G73', 'B94', 'A36', 'B102'], dtype=object)
data['客舱'].nunique() # 不同种类数据的个数
147
② 将文本变量用数值变量12345表示
方法一:replace

replace官方文档

data['性别(数值)'] = data['性别'].replace(['female','male'], [0, 1])
data.head()
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口 年龄(离散化) 性别(数值)
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C 4 1
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C 4 0
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C 4 1
438 439 0 1 Fortune, Mr. Mark male 64.0 1 4 19950 263.0000 C23 C25 C27 S NaN 1
341 342 1 1 Fortune, Miss. Alice Elizabeth female 24.0 3 2 19950 263.0000 C23 C25 C27 S 3 0
方法二:Series.map()

map官方文档

data['性别(数值)'] = data['性别'].map({'male':1, 'female':0})

当文本类型的种类较少时,可以采用以上两种方法,如性别,但如 客舱这种复杂信息,这两种方法就难以应对。

方法三:使用sklearn.preprocessing的LabelEncoder

LabelEncoder方法

method describetion
fit(y) Fit label encoder
fit_transform(y) Fit label encoder and return encoded labels
get_params([deep]) Get parameters for this estimator.
inverse_transform(y) Transform labels back to original encoding.
set_params(**params) Set the parameters of this estimator.
transform(y) Transform labels to normalized encoding.
from sklearn.preprocessing import LabelEncoder

for feat in ['船票信息', '客舱']: #对 船票信息,客舱 两列文本信息分别进行数值化处理
    encoder = LabelEncoder()
    data[feat + '(数值化)'] = encoder.fit_transform(data[feat].astype(str))
    #astype()函数可用于转化dateframe某一列的数据类型,不使用astype会报错
data.sort_values(by='乘客ID').head()
乘客ID 是否幸存 乘客等级 乘客姓名 性别 年龄 兄妹个数 父母小孩个数 船票信息 票价 客舱 登船港口 年龄(离散化) 性别(数值) 船票信息(数值化) 客舱(数值化)
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 2 1 523 147
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 5 0 596 81
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 3 0 669 147
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 4 0 49 55
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 4 1 472 147
③将文本变量用one-hot编码表示

将已经离散化、数值化的列删除

data_encoded = data.drop(['性别', '年龄', '客舱', '船票信息'], axis = 'columns')
data_encoded.head()
乘客ID 是否幸存 乘客等级 乘客姓名 兄妹个数 父母小孩个数 票价 登船港口 年龄(离散化) 性别(数值) 船票信息(数值化) 客舱(数值化)
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez 0 1 512.3292 C 4 1 608 34
258 259 1 1 Ward, Miss. Anna 0 0 512.3292 C 4 0 608 147
737 738 1 1 Lesurer, Mr. Gustave J 0 0 512.3292 C 4 1 608 15
438 439 0 1 Fortune, Mr. Mark 1 4 263.0000 S NaN 1 95 63
341 342 1 1 Fortune, Miss. Alice Elizabeth 3 2 263.0000 S 3 0 95 63
登船港口_1hot = pd.get_dummies(data['登船港口'], prefix='登船港口')
登船港口_1hot
登船港口_C 登船港口_Q 登船港口_S
679 1 0 0
258 1 0 0
737 1 0 0
438 0 0 1
341 0 0 1
... ... ... ...
481 0 0 1
633 0 0 1
674 0 0 1
732 0 0 1
815 0 0 1

891 rows × 3 columns

data_encoded = pd.concat([data_encoded,登船港口_1hot], axis=1)
data_encoded.head()
乘客ID 是否幸存 乘客等级 乘客姓名 兄妹个数 父母小孩个数 票价 登船港口 年龄(离散化) 性别(数值) 船票信息(数值化) 客舱(数值化) 登船港口_C 登船港口_Q 登船港口_S
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez 0 1 512.3292 C 4 1 608 34 1 0 0
258 259 1 1 Ward, Miss. Anna 0 0 512.3292 C 4 0 608 147 1 0 0
737 738 1 1 Lesurer, Mr. Gustave J 0 0 512.3292 C 4 1 608 15 1 0 0
438 439 0 1 Fortune, Mr. Mark 1 4 263.0000 S NaN 1 95 63 0 0 1
341 342 1 1 Fortune, Miss. Alice Elizabeth 3 2 263.0000 S 3 0 95 63 0 0 1

3.3.3 从纯文本提取特征

# 跳过:正则表达式

3.3.4 数据保存

data_encoded.to_csv('train_fin.csv')
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐