Kaggle泰坦尼克号生存预测挑战——数据分析

Kaggle泰坦尼克号生存预测挑战

    这是kaggle上Getting Started 的Prediction Competition,也是比较入门和简单的新人赛,我的最好成绩好像有进入top8%,重新地回顾巩固一下这个比赛,我将分成三个部分:

先修知识

  • numpy
  • pandas
  • matplotlib
  • seaborn
  • sklearn

赛题地址:Titanic: Machine Learning from Disaster

泰坦尼克号的沉没

    1912年4月15日,在她的处女航中,被普遍认为“沉没”的RMS泰坦尼克号与冰山相撞后沉没。

    不幸的是,船上没有足够的救生艇供所有人使用,导致2224名乘客和机组人员中的1502人死亡。虽然幸存有一些运气,但似乎有些人比其他人更有可能生存。

    在这一挑战中,我们要求您建立一个预测模型来回答以下问题:“什么样的人更有可能生存?” 使用乘客数据(即姓名,年龄,性别,社会经济舱等)

    任务分析:这是一个分类任务,建立模型预测幸存者

数据集

  • 训练集:891*12,含891个样本,11+1个特征(一个是target)
  • 测试集:418*11,含418个样本,11个特征

Overview:

  • PassengerId:乘客ID — id号作用不大,考虑删除
  • Survived:存活 (target) ---- 标签:1代表存活 0 代表没有幸存
  • Pclass:舱位等级 ---- 分成三个等级 1 2 3
  • Name:姓名 — 由于外国的姓氏有等级之分,有意义
  • Sex:性别 — 女士是否优先??
  • Age:年龄 — 年轻人可能存活多??
  • SibSp:泰坦尼克号上的兄弟姐妹/配偶数 — 有待考查
  • Parch:泰坦尼克号上的父母/子女数量 — 有待考查
  • Ticket:票据 — 有待考查
  • Fare:票价 — 票价高的可能待遇高
  • Cabin:船舱号 — 不同的船舱或许获得求生不同
  • Embarked:登船港口 ---- C = Cherbourg;Q = Queenstown;S = Southampton

代码实现

导入相关的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
seed =2020
数据概览
  1. 加载数据方法 :pd.read_csv(),pd.read_table()

    • pd.read_csv():读取以‘,’分割的文件到DataFrame,用于读取csv文件(csv用逗号符分隔字符段)
    • pd.read_table():读取以‘\t’分割的文件到DataFrame,用于读取tsv文件(tsv用制表符分隔字符段)
    • 实质上两个方法都是通用的,函数中参数sep可以选定分隔符的类型

    例如用read_csv()读取tsv文件,df = pd.read_csv(file_path,sep='\t')

  2. 处理大型文件或内存不足时,采用分块读取方式:

    • 使用参数chunksize指定文件块的大小(用于迭代)

    df = pd.read_csv(file_path,chunksize = 100)
    for i in df: ##用循环的方式即可迭代读取DataFrame
    print(i)

  3. 更多常用参数在这里插入图片描述

##加载数据  不建议把特征名转成中文,在画图时可能出现乱码
train_df = pd.read_csv('data_train.csv')
test_df = pd.read_csv('data_test.csv')
##数据预览 查看前5行的数据
train_df.head()

在这里插入图片描述

test_df.head()

在这里插入图片描述

  • DataFrame.info(): 可以对数据进行简要的概览,非空样本数,特征行的类型,特征数
  • DataFrame.describe(): 输出数值型特征的一些统计量
train_df.info()

在这里插入图片描述

train_df.describe()

在这里插入图片描述

test_df.info()

在这里插入图片描述

test_df.describe()

在这里插入图片描述

数据的探索性分析EDA

### 可以根据自己的需求封装一个函数
def _data_info(data,categorical_features):
    print('number of train examples = {}'.format(data.shape[0]))
    print('number of train Shape = {}'.format(data.shape))
    print('Features={}'.format(data.columns))
    print('\n--------输出类别特征的种类--------')
    for i in categorical_features:
        if i in list(data.columns):
            print("train:"+i+":",list(data[i].unique()))
    print('\n--------缺失值--------')
    missing = data.isnull().sum()
    missing = missing[missing > 0]
    print(missing)
    missing.sort_values(inplace=True)
    missing.plot.bar()
    plt.show()
def data_info(data_train,data_test,categorical_features):
    print('--------训练集基本概况--------')
    _data_info(data_train,categorical_features)
    print('\n\n--------测试集基本概况--------')
    _data_info(data_test,categorical_features)

数据概况、类别特征、缺失值情况
  • 训练集的样本数:891, 特征数:11+1(一个标签)

  • 测试集的样本数:418, 特征数:11(一个标签)

    类别特征的情况:

    1. Survived (标签): 取值{0,1},对应未幸存和幸存
    2. Pclass: 取值{1,2,3},对应船舱级别
    3. Sex: 取值{male,female},对应性别
    4. Cabin: 船舱号
    5. Embarked:取值{S,C,Q}。对应登船港口
data_info(train_df,test_df,['Survived','Pclass','Sex','Cabin','Embarked','SibSp','Parch'])

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

缺失值情况

了解了缺失值的情况后,可以对其进行简单的填充

  1. 训练集缺失值:
  • Age : 177
  • Cabin: 687
  • Embarked: 2
  1. 测试集缺失值:418
  • Age:86
  • Fare : 1
  • Cabin : 327
#将数据合并一起处理,添加一个train特征用于区分训练集和测试集
train_df['train'] = 1
test_df['train'] = 0
data_df = pd.concat([train_df,test_df],sort=True).reset_index(drop=True)
## 删除PassengerId特征
data_df.drop('PassengerId',inplace=True,axis=1)

## 先将非数字的类别特征数字化
from sklearn import preprocessing
ler_sex = preprocessing.LabelEncoder()
ler_sex.fit(data_df['Sex'])
data_df['Sex'] = ler_sex.transform(data_df['Sex'])

Embarked

缺失数量少,考虑使用众值进行填充

data_df['Embarked'].fillna(data_df['Embarked'].mode()[0],inplace=True)
## 填充完Embarker后,先将非数字的类别特征数字化
ler_Embarked = preprocessing.LabelEncoder()
ler_Embarked.fit(data_df['Embarked'])
data_df['Embarked'] = ler_Embarked.transform(data_df['Embarked'])
Age

177 + 86 891 + 418 ≈ 20 % {177+86\over891+418}\approx 20\% 891+418177+8620%

缺失率约20%,考虑对齐进行填充,如果直接采用数据集的数据特征进行填充,效果可能可能不是很好

尝试结合其他聚合特征对Age进行填充,从相关性程度分析中可以看出,Pclass的程度较大

abs(data_df.corr()['Age']).sort_values(ascending=False)
Age         1.000000
Pclass      0.408106
SibSp       0.243699
Fare        0.178740
Parch       0.150917
Embarked    0.080195
Survived    0.077221
Sex         0.063645
train       0.018528
年龄分布
y = data_df['Age']
plt.figure(1)
plt.title('Distribution of Age')
sns.distplot(y, kde=True)

## 不同性别的年龄分布,可以看出他们的分布趋于相同
plt.figure(2);
Age_Sex0 = data_df.loc[data_df['Sex']==0,'Age']
Age_Sex1 = data_df.loc[data_df['Sex']==1,'Age']
plt.title('Distribution of Age in Sex');
plt.legend(['Sex0','Sex1']);
sns.distplot(Age_Sex0, kde=True);
sns.distplot(Age_Sex1, kde=True);

在这里插入图片描述

不同Pclass中的年龄分布,从其中的分布确实能看出有一些差别
Age_p1 = data_df.loc[data_df['Pclass']==1,'Age']
Age_p2 = data_df.loc[data_df['Pclass']==2,'Age']
Age_p3 = data_df.loc[data_df['Pclass']==3,'Age']
sns.distplot(Age_p1,kde=True,color='b')
sns.distplot(Age_p2,kde=True,color='green')
sns.distplot(Age_p3,kde=True,color='grey')
plt.title('Distribution of Age in Pclass')
plt.legend(['p1','p2','p3'])

在这里插入图片描述

Age_Pclass = data_df.groupby([ 'Pclass']).median()['Age']
for pclass in range(1, 4):
    print('Median age of Pclass {}: {}'.format(pclass,Age_Pclass [pclass]))
print('Median age of all passengers: {}'.format(data_df['Age'].median()))

# 根据Pclass填充Age值
data_df['Age'] = data_df.groupby(['Pclass'])['Age'].apply(lambda x: x.fillna(x.median()))
Fare

Fare缺失的样本只有一个,可以考虑直接用数据集的统计特征填充

不过看到SibSp,Parch都等于0,说明购置的是单人票,Plass又是机舱等级,可以考虑聚合以上属性

#查看Fare缺失的样本
data_df[data_df['Fare'].isnull()]

在这里插入图片描述

## Pclass对价格的影响很大
abs(data_df.corr()['Fare']).sort_values(ascending=False)
Fare        1.000000
Pclass      0.558629
Survived    0.257307
Embarked    0.238005
Parch       0.221539
Age         0.202512
Sex         0.185523
SibSp       0.160238
train       0.030831
## 聚合数据属性
print(data_df.groupby(['Pclass', 'Parch','SibSp','Embarked']).Fare.max()[3][0][0][0])#18.7875
print(data_df.groupby(['Pclass', 'Parch','SibSp','Embarked']).Fare.min()[3][0][0][0])#4.0125
print(data_df.groupby(['Pclass', 'Parch','SibSp','Embarked']).Fare.median()[3][0][0][0])#7.2292
print(data_df.groupby(['Pclass', 'Parch','SibSp','Embarked']).Fare.mean()[3][0][0][0])#7.923984210526318
## 选择中位数进行填充
data_df['Fare'].fillna(data_df.groupby(['Pclass', 'Parch','SibSp','Embarked'])['Fare'].median()[3][0][0][0],inplace=True)
Cabin

Cabin缺失较多,如果没有很好的填充数据的方法时,建议将其直接删除。

data_df.drop('Cabin',inplace=True,axis=1)

数据缺失填充完成

继续分析数据
#从data_df得到训练集
train_data = data_df[data_df.train==1]
train_data['Survived'] = train_df['Survived']
train_data.drop('train',axis=1,inplace=True)
#从data_df得到测试训练集
test_data = data_df[data_df.train==0]
test_data.drop(['Survived','train'],axis=1,inplace=True)

特征相关程度分析

训练集
train_data.corr()

在这里插入图片描述

### 从幸存和性别成负相关程度较大
### 从幸存和Pclass 成负相关程度较大
### 从幸存和Fare 成负相关程度较大
train_data.corr()['Survived'].sort_values(ascending=False)
Survived    1.000000
Fare        0.257307
Parch       0.081629
SibSp      -0.035322
Age        -0.046230
Embarked   -0.167675
Pclass     -0.338481
Sex        -0.543351

绘制特征相关程度热图

plt.figure( figsize=(10, 10))
plt.title('Train Set Correlation HeatMap ',y=1,size=16)
sns.heatmap(train_data.corr(),square = True,  vmax=0.7,annot=True,cmap='Accent')

在这里插入图片描述

存活情况
plt.bar(['Not Survived','Survived'],train_data['Survived'].value_counts().values)
plt.title('Train_Set_Survived')

在这里插入图片描述

测试集

test_data.corr()

在这里插入图片描述

plt.figure( figsize=(10, 10))
plt.title('Test Set Correlation HeatMap ',y=1,size=16)
sns.heatmap(test_data.corr(),square = True,  vmax=0.7,annot=True,cmap='Accent')

在这里插入图片描述

连续性数据分布的情况

从Age、Fare的生存情况分布中可以看出的是

  • Age:年龄小的似乎生存率高一些,不同年龄段生存不一样,后续可以考虑对数据分桶操作
  • Fare:可以看出船票价格高的生存率高一些
    Age和Fare在训练集和测试集上的分布比较一致

continue_features = ['Age', 'Fare']
survived = train_data['Survived'] == 1

fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(20, 20))
plt.subplots_adjust(right=1.5)

for i, feature in enumerate(continue_features):    
    sns.distplot(train_data[~survived][feature], label='Not Survived', hist=True, color='#e74c3c', ax=axs[0][i])
    sns.distplot(train_data[survived][feature], label='Survived', hist=True, color='#2ecc71', ax=axs[0][i])
    
    sns.distplot(train_data[feature], label='Training Set', hist=False, color='#e74c3c', ax=axs[1][i])
    sns.distplot(test_data[feature], label='Test Set', hist=False, color='#2ecc71', ax=axs[1][i])
    
    axs[0][i].set_xlabel('')
    axs[1][i].set_xlabel('')
    
    for j in range(2):        
        axs[i][j].tick_params(axis='x', labelsize=20)
        axs[i][j].tick_params(axis='y', labelsize=20)
    
    axs[0][i].legend(loc='upper right', prop={'size': 20})
    axs[1][i].legend(loc='upper right', prop={'size': 20})
    axs[0][i].set_title('Distribution of Survival in {}'.format(feature), size=20, y=1.05)

axs[1][0].set_title('Distribution of {} Feature'.format('Age'), size=20, y=1.05)
axs[1][1].set_title('Distribution of {} Feature'.format('Fare'), size=20, y=1.05)
        
plt.show()

在这里插入图片描述

类别特征分布情况

  • Embarked :取值为0时的,幸存率较高
  • Sex: 取值为0时,幸存率较高
  • Pclass :幸存率由1到3 递减
  • SibSp和Parch的幸存率大致分布一致,可以考虑将他们合并成一个Family特征
Categorical_features = ['Embarked', 'Parch','SibSp','Sex', 'Pclass']

fig, axs = plt.subplots(ncols=2, nrows=3, figsize=(20, 20))
plt.subplots_adjust(right=1.5, top=1.25)

for i, feature in enumerate(Categorical_features, 1):    
    plt.subplot(2, 3, i)
    sns.countplot(x=feature, hue='Survived', data=train_data)
    
    plt.tick_params(axis='x', labelsize=20)
    plt.tick_params(axis='y', labelsize=20)
    
    plt.xlabel('{}'.format(feature), size=20, labelpad=15)
    plt.ylabel('Passenger Count', size=20, labelpad=15)    
    plt.legend(['Not Survived', 'Survived'], loc='upper center')
    plt.title('Count of Survival in {} Feature'.format(feature), size=20, y=1.05)
plt.show()


fig, axs = plt.subplots(ncols=2, nrows=3, figsize=(15, 15))
plt.subplots_adjust(right=1.5, top=1.25)
for i, feature in enumerate(Categorical_features, 1):    
    plt.subplot(2, 3, i)
    sns.pointplot(feature,y='Survived',data=train_data)
    
    plt.tick_params(axis='x', labelsize=20)
    plt.tick_params(axis='y', labelsize=20)
    
    plt.xlabel('{}'.format(feature), size=20, labelpad=15)
    plt.ylabel('Passenger Count', size=20, labelpad=15)    
    plt.title('Rate of Survival in {} Feature'.format(feature), size=20, y=1.05)
plt.show()

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

保存csv文件

train_data.to_csv('./train.csv',index=False)
test_data.to_csv('./test.csv',index=False)
  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值