「一起学」Udaicty 数据分析(入门)P2 项目总结

失踪人口回归了~
是的~你没看错,迟早会更新专栏终于更新了,经历了搬家、业务线调整,上完李叫兽的课后,又顺手去 Udacity 修了数据分析(入门)课程和机器学习(进阶)。真心没有时间啊~ 顺利三个月完成了 Udacity 的数据分析课程~ 学完后开始撸机器学习了~不过因为学习的过程比较快,所以想通过写文章的方式重新过一下所学的东西,夯实下~ 如果有任何疑问也欢迎留言~ 最后,最重要的就是如果你也想在 Udacity 学习数据分析或者机器学习的话,可以输入这个优惠码哦:28716825 ,便宜300块~

P2 项目背景

完成了 P1项目后,我就从统计学课程转移到 Python 课程,课程期间学习使用 Python 库 NumPy、Pandas 以及 Matplotlib。所以 P2 阶段项目当然就是要使用 Pandas 和 NumPy 做啦~ 在 P2 项目中,我需要从两个数据集中选择一个来分析,最后我选择了网上比较流行的泰坦里克号数据。我需要通过分析数据,调查哪些因素会让船上的人生还率更高?

我的答案

一、基本信息

本次分析的数据,来源于 Kaggle 网站上的泰坦尼克号生还者数据。包括泰坦尼克号上 2224 名乘客和船员中 891 名的人口学数据和乘客基本信息。
从 Kaggle 网站上可以得到船上每位旅客的特征:

  • Survived:是否存活(0代表否,1代表是)
  • 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
from IPython.display import display
import matplotlib.pyplot as plt
%matplotlib inline
from collections import Counter

import seaborn as sns
sns.set(color_codes=True)
# 加载数据集
in_file = 'titanic-data.csv'
full_data = pd.read_csv(in_file)
# 预览下前几项乘客数据
display(full_data.head())

# 我们发现像在 Cabin 里的数据有 NaN 的数据,使用 .isnull() 来看看有多少缺省数据。
#data.isnull().sum()将缺失项的数据全部加起来
print(full_data.isnull().sum())

# Age、Cabin 和 Embarked 有缺失,特别是 Cabin,虽然船舱编号可以反映船舱所处的位置,但是缺省太多。
# 而且在缺少泰坦尼克号设计图的情况下,此字段对我帮助不大,所以决定删除 Cabin 字段。
clean_data = full_data.drop(['Cabin'], axis=1)

# 对于 Age 的处理就比较麻烦了,按照常识估计,年龄对于生还率影响肯定非常大,当然不能删除此字段。
# 所以基于此,我决定使用随机值的方式填充缺省值。同时考虑到随机值的合理性。
# 我决定从(均值 - 标准差)和(均值 + 标准差)之间取随机值:
average_age_clean_data   = clean_data["Age"].mean()
std_age_clean_data       = clean_data["Age"].std()
count_nan_age_clean_data = clean_data["Age"].isnull().sum()
randonNum = np.random.randint(average_age_clean_data - std_age_clean_data, average_age_clean_data + std_age_clean_data, size = count_nan_age_clean_data)
# 将 Age 中的 NaN 替换成随机值:
clean_data["Age"][np.isnan(clean_data["Age"])] = randonNum
# 对于 Embarked 来说,它缺失的比较少,而且此字段只有三种可能 —— C、Q、S。
# 这里我采用了偷懒的方法就是将众数填填充到缺省内。
# 找到众数:
embarked_mode = full_data["Embarked"].mode()
print embarked_mode

接着

# 将众数填充到缺省内:
clean_data["Embarked"] = clean_data["Embarked"].fillna("S”)
# 最后看看清洗过后的数据
print(clean_data.isnull().sum())

清洗完数据后,我们就可以进入探索数据阶段。

四、探索数据

此部分开始我们通过数据可视化的方式,分析「哪些因素会让船上的人生还率更高?」

4.1 考虑年龄因素

# 先看看整体数据的年龄分布情况:
clean_data['Age'].hist(bins=40)
plt.title('Distribution of Age')
plt.xlabel('Age')
plt.ylabel('Number of people')

# 从图中可以得出,大部分的乘客是 20 ~ 35岁。
# 我们再来看看不同年龄段的乘客的获救情况:
nonsurv_age = clean_data[clean_data['Survived'] == 0]['Age']
surv_age = clean_data[clean_data['Survived'] == 1]['Age']
plt.hist(nonsurv_age, color = 'r', alpha=0.8, label = 'Did not survive')
plt.hist(surv_age, color = 'g', alpha=0.8, label = 'Survived')
plt.title('Number of Survived Passenger and Number of Nonsurvived Passenger')
plt.xlabel('Age')
plt.ylabel('Number of people')

从上图可以看到,20岁以下的乘客获救人数高于未获救人数,但是这还不足以完全说明年纪越小生还率越高。我们还需要看看各年龄段的生还率如何。

# 因为年龄是个连续值,所以我们在计算生还率的时候,需要先分组。
bins=np.arange(0,90,10)
clean_data['Age_group'] = pd.cut(clean_data['Age'], bins)
clean_data.groupby(['Age_group','Survived'])['Survived'].count().unstack().plot(kind='bar',stacked=True)

plt.title('Distribution of Survived and Nonsurvived by Age Group')
plt.xlabel('Age Group')
plt.ylabel('Number of people')

#计算每组的生还率

clean_data.groupby('Age_group')['Survived'].mean().plot(kind='bar')

plt.title('Survival rate by Age Group')
plt.xlabel('Age Group')
plt.ylabel('Number of people')


从上图可以看到,0 到 10 岁年龄段的人生还率远高于其他年龄段的人。所以我们可以得出第一个解决:年纪对获救的概率有影响。

4.2 考虑船票等级因素

我们再来看看等级因素对获救率的影响。
首先我们统计下各等级的船舱的人数,以及获救人数和未获救人数。

####################################
#            第二次提交              #
####################################

#根据评审建议,将上述代码写成函数方便后续调用。
def survival_count(key):
    clean_data.groupby([key,'Survived'])['Survived'].count().unstack().plot(kind='bar',stacked=True)
    plt.ylabel('Count')
    plt.title('Number of Survived Passenger Number by {}'.format(key))

# 调用
survival_count('Pclass')

#同时再将生还率的计算改写成函数。
def survival_rate(key):
    clean_data.groupby(key)['Survived'].mean().plot(kind='bar')
    plt.ylabel('Survival rate')
    plt.title('Survival rate by {}'.format(key))

# 调用
survival_rate('Pclass')


由上方柱图可以看出,一等舱的获救率高于其他等级的船舱,且从图中可以看出获救率随等级的降低而降低。所以我们可以得出一个结论就是:船舱等级越高获救的概率越高。

4.3 考虑性别因素

最后我们再来看看性别因素对获救的率的影响。
首先我们来统计下男、女人数和获救及未获救人数。

# 调用前面所写函数
survival_count('Sex')

由上方的堆叠柱状图可以看出,女性的获救比例较高,所以性别也会对获救率有影响。

# 再来看看获救率情况
survival_rate('Sex')


由上方的柱状图可以看出,女性的获救率远高于男性。所以我们可以得出:女性获救率高于男性

4.4 综合考虑船舱等级和性别因素

clean_data.groupby(['Pclass', 'Sex']).count()['Survived'].unstack().plot(kind='bar')
plt.ylabel('Count')
plt.title('Number of passenger by Pclass and Sex')

# 我们再来看看生还率情况
clean_data.groupby(['Pclass', 'Sex']).mean()['Survived'].unstack().plot(kind='bar')
plt.ylabel('Survival Rate')
plt.title('Survival rate of passenger by Pclass and Sex')


由上方的柱状图可以看出,一等舱的女性的获救率远高于男性。

五、总结

总结上述分析,我们可以得出以下三个结论:

  1. 年龄对获救率有影响,一般儿童的获救率比较高。
  2. 船舱等级对获救率有影响,等级越高获救率越高。
  3. 性别对获救有影响。女性获救率高于男性。

但是我们也要看到这些结论背后的限制:

  1. 样本是从铁达尼号灾难中 2224 名乘客和船员中 891 名,样本容量足够。
  2. 第一条结论中的 Age 字段缺省较多,我是通过从(均值 - 标准差)和(均值 + 标准差)之间取随机值的方式填充缺省数值,这样不一定能够很好地反应事实。
  3. 在探索年龄对生还情况的影响的时候,发现 50 ~ 60 岁这个年龄段的生还率出现一些异常,其生还率比 20 ~ 30 岁的年轻人还要高。怀疑还有一些数据集中不存在的其他变量也会对存活率有影响。
Comments
Write a Comment