泰坦尼克号沉没
- 1.本系列基于新生大学课程《Python编程&数据科学入门》和公开的参考资料;
- 2.文章例子基于python3.6,使用Windows系统(除了安装,其余基本没有影响);
- 3.我是纯小白,所以,错误在所难免,体系会逐渐成熟;如果您发现了错误,也烦请帮我指出来,在此先谢过了。
这次课主要是通过一个案例来学习数据分析的流程和方法。主要有学习三个内容:
- 数据分析的流程
- 数据清洗(缺失值的处理)
- 数据探索的方法
数据分析的流程
python最强大的是数据分析。下面是数据分析的流程图:
数据分析流程图数据分析的核心是问题,为了解决这个问题,开始采集数据,而我们采集的数据经常出现不完整,内容不全等情况,所以要对数据进行清洗,让数据变的方便使用。
数据完整之后,就可以开始对数据的探索了,期待从中发现规律,解决问题,在探索的过程中通常会发现新的问题,继续往下探索就需要新的数据,这时通常会再次重复上面的过程。
当数据探索的差不多了,就可以把结论变成一个模型进一步来分析和验证(这不是python的工作了),最后将结果发布出来,用于决策。
这个流程不论在哪个行业都是通用的。下面我们就以泰坦尼克的数据来走一遍这个流程。
我们想要解决的问题是:船只沉没后,哪些因素能够影响生还的概率?
泰坦尼克的数据是公开的,我们不需要单独采集数据了。
先导入这个数据:
#读取常用的包,并进行常规设置
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
# 读取数据
titanic_df = pd.read_csv('lesson/titanic.csv')
titanic_df.head()
导入后,我们可以看一看都有哪些字段:
PassengerId: 乘客的id
Survival: 是否幸存 0 = No, 1 = Yes
Pclass: 舱位 class 1 = 1st, 2 = 2nd, 3 = 3rd
Name: 姓名
Sex: 性别
Age: 年龄
SibSp: 船上兄弟姐妹以及配偶的个数
Parch: 船上父母以及者子女的个数
Ticket: 船票号码
Fare: 票价
Cabin: 船舱号码
Embarked: 登船码头 C = Cherbourg, Q = Queenstown, S = Southampton
这13个字段可以分为三类:字符串、数值变量、分类变量。
字符串不需要讲解,分类变量的内容可以分为有限的几类,比如Survived有0和1两类,Pclass有1、2、、3三类,Sex有male、female两类,SibSp、Parch、Embarked等是分类变量;而数值变量就是其内容是一个数字,比如PassengerId、Ticket、Fare等等。
导入数据后,我们可以观察一下这个数据:
titanic_df.describe(include = [np.object])#列出分类变量
# top代表最高频的一个值,freq代表最高频值对应的频率
看看各个舱位的占比情况:
# 使用group_by函数
(titanic_df.groupby('Pclass').agg('size')/len(titanic_df)).sort_values(ascending = True)
Pclass
2 0.206510
1 0.242424
3 0.551066
dtype: float64
查看登船码头人数分布的百分比:
# 方法1:使用 value_counts
titanic_df.Embarked.value_counts()/ len(titanic_df)
S 0.722783
C 0.188552
Q 0.086420
Name: Embarked, dtype: float64
# 方法2:使用 group_by
(titanic_df.groupby('Embarked').agg('size')/len(titanic_df)).sort_values(ascending = True)
Embarked
Q 0.086420
C 0.188552
S 0.722783
dtype: float64
数据清洗(缺失值的处理)
我们再观察一下这个数据的整体情况:
Age、Cabib、Embarked这3列的值都是不全的,它们被赋予了NaN值,也就是Not a Number的意思。
为了不影响分析数据,我们要把这些值填满,这就叫缺失值处理。
处理起来主要有三种方法:
- 直接丢掉这个变量。 -- 删除某一列数据
- 用平均值或中位数填补缺失值。像Age这样的重要变量,有20%左右的缺失值,我们可以考虑用中位值来填补。-- 填补缺失值
- 删除带缺失值的行。因为其他非缺失的变量可能提供有用的信息,删除行有时影响不会太大。
第一和第三种方法比较简单,直接输入命令就可以。下面我们来看如何填补年龄字段的缺失值。
填补通常用中位数。
# 重新载入数据,防止数据改变.
titanic_df = pd.read_csv('lesson/titanic.csv')
# 获取数据的平均值
age_med1 = titanic_df.Age.median()
# 使用fillna函数填充缺失值,inplace表示在原数据上直接修改
titanic_df.Age.fillna(age_med1, inplace=True)
可以看到,Age已经有891个,说明已经被填补好了。
如果考虑到男女可能差异较大的因素,也可以尝试用男女乘客各自年龄的中位数来填补。
# 重新载入数据,防止数据被改变了
titanic_df = pd.read_csv('lesson/titanic.csv')
# 分组计算男女乘客的中位数
age_med2 = titanic_df.groupby('Sex').Age.median()
age_med2
# 重新设置索引,将Sex为索引
titanic_df.set_index('Sex', inplace=True)
# 使用fillna填充
titanic_df.Age.fillna(age_med2, inplace = True)
#恢复索引
titanic_df.reset_index(inplace= True)
titanic_df.Age.describe()
下面同时考虑姓名和仓位的因素进行填充。
# 重新导入原始数据
titanic_df = pd.read_csv('lesson/titanic.csv')
# 分组计算不同仓位男女年龄的中位数,得到一个Serics数据,索引为Pclass、Sex
age_med3 = titanic_df.groupby(['Pclass',"Sex"]).Age.median()
age_med3
# 设置Pclass、Sex为索引,按照两列进行索引inplace=True表示直接替换原来的索引
titanic_df.set_index(['Pclass','Sex'],inplace=True)
# 用fillna填充
titanic_df.Age.fillna(age_med3, inplace=True)
#恢复索引
titanic_df.reset_index(inplace=True)
#查看填充结果
titanic_df.Age.describe()
数据探索和分析
1.计算舱位和生还概率的关系
Survived 是0-1,所以均值就代表其生还概率。
#用groupby方法来实现
titanic_df[['Pclass','Survived']].groupby('Pclass').mean()
用透视表pivot_talbe函数(透视表)可以实现同样的功能。
# values代表聚合后被施加计算的值,这里施加的是mean函数
# index:是分组用的变量
# aggfunc是定义施加的函数
titanic_df.pivot_table(values='Survived', index='Pclass',aggfunc=np.mean)
# 还可以画出条形图
sns.barplot(data = titanic_df, x='Pclass', y= 'Survived',ci=None)
所以,头等舱的生还概率最高,二等舱次之,三等舱最低。
2.再来看性别与生还的关系
#使用groupby函数
titanic_df[['Sex','Survived']].groupby('Sex').mean()
# 使用pivot_talbe函数
titanic_df.pivot_table(values = 'Survived', index = 'Sex', aggfunc = np.mean)
# 绘制条形图
sns.barplot(data= titanic_df, x= 'Sex', y ='Survived', ci = None)
plt.show()
结论:女性的生还率远远大于男性
3.综合考虑女性和舱位于生还的概率
titanic_df[["Pclass",'Sex','Survived']].groupby(['Pclass','Sex']).mean()
# 使用pivot_table方法
titanic_df.pivot_table(values='Survived', index=['Pclass', 'Sex'],aggfunc=np.mean )
# 方法3:同样用pivot_table方法,将其中一个索引作为列
# columns指定另一个分类变量
# 绘制条形图
sns.barplot(data=titanic_df, x='Pclass', y = 'Survived', hue='Sex', ci=None)
# 绘制折线图
sns.pointplot(data=titanic_df, x='Pclass', y = 'Survived', hue='Sex', ci=None)
4.分别使用groupby和pivot_talbe,计算在不同舱位中男女乘客的人数。
# 方法1 groupby
titanic_df.groupby(['Pclass','Sex']).Sex.count()
Pclass Sex
1 female 94
male 122
2 female 76
male 108
3 female 144
male 347
Name: Sex, dtype: int64
# 方法2 groupby
titanic_df[['Pclass','Sex','Ticket']].groupby(['Pclass','Sex']).count()
# 方法3 pivot_talbe
titanic_df.pivot_table(values='Ticket', index=['Pclass','Sex'], aggfunc='count')
# 方法4
titanic_df.pivot_table(values= 'Ticket',index='Pclass',columns='Sex',aggfunc='count')
5.绘制生还组和罹难组的年龄分布直方图
# 用seaborn包里的FacetGrid().mpa来快速生成。
# bins代表横轴取值的单位大小
# normed表示纵轴的值按总数进行了比例换算
sns.FacetGrid(titanic_df).map(plt.hist, 'Age', bins = 30, normed = True)
# col是列的意思,可以指定在一行中显示显示区分。
sns.FacetGrid(titanic_df, col = 'Survived').map(plt.hist, 'Age', bins = 30, normed = True)
<seaborn.axisgrid.FacetGrid at 0xb37c74b7f0>
结论:
1.儿童的生还率最高,而其他的年龄层次都不明显。
6.考虑舱位因素,绘制生还组和罹难组的年龄分布直方图(作业 8-3)。
提示:FacetGrid参数中同时设置col和row
sns.FacetGrid(titanic_df,col = 'Survived', row = 'Pclass').map(plt.hist, 'Age', bins=30, normed=True)
7.查看落在不同年龄区间的人数
- 将连续型的变量零散化
将连续变化的值划分为几个区间,落在同一个区间的就有些同一个符号来表示。这种方法能够增加数据分析的便利性。
#用pandas中的cut函数来表示。
titanic_df['Ageband'] = pd.cut(titanic_df.Age, 4)
titanic_df.head()
增加了一列Ageband。
# 方法一:用value_counts函数
titanic_df.Ageband.value_counts(sort=False)
(0.34, 20.315] 179
(20.315, 40.21] 562
(40.21, 60.105] 128
(60.105, 80.0] 22
Name: Ageband, dtype: int64
# 方法二:用pivot_table
titanic_df.pivot_table(values='Survived', index='Ageband',aggfunc='count')
# 查看各个年龄区间的生还概率
# 方法1:
titanic_df[['Survived','Ageband']].groupby('Ageband').mean()
#方法2:用pivot_table
titanic_df.pivot_table(values='Survived',index='Ageband', aggfunc=np.mean)
# 方法3:画出这样一个条形图
sns.barplot(data=titanic_df, x='Ageband',y='Survived')
plt.xticks(rotation= 45)
8.查看年龄、性别与生还的概率。
其实方法都是一样的。
#第一种方法:用groupby
titanic_df.groupby(['Ageband','Sex']).Survived.mean()
Ageband Sex
(0.34, 20.315] female 0.688312
male 0.284314
(20.315, 40.21] female 0.756614
male 0.166220
(40.21, 60.105] female 0.755556
male 0.192771
(60.105, 80.0] female 1.000000
male 0.105263
Name: Survived, dtype: float64
#第二种方法:grouby
titanic_df[['Ageband','Sex','Survived']].groupby(['Ageband','Sex']).mean()
# 第三种方法:pivot_table
titanic_df.pivot_table(values='Survived', index=['Ageband','Sex'], aggfunc=np.mean)
# 第四种方法:pivot_table
titanic_df.pivot_table(values='Survived',index='Ageband',columns='Sex',aggfunc=np.mean)
# 方法5:用图示表示,画出条形图barplot
sns.FacetGrid(titanic_df, col ='Sex', row='Ageband').map(plt.hist, 'Survived')
# 方法5:用折线图
sns.pointplot(data=titanic_df, x= 'Ageband', y='Survived', hue = 'Sex', ci=None)
plt.xticks(rotation=45)
(array([0, 1, 2, 3]), <a list of 4 Text xticklabel objects>)
8.分析年龄、舱位、性别与生还概率的关系
# 第一种方法
titanic_df.pivot_table(values='Survived', index='Ageband', columns=['Sex','Pclass'],aggfunc='mean')
# 第二种方法:第一步,先用sns.pointplt来绘制舱位、性别与生还概率的关系
sns.pointplot(data=titanic_df, x='Pclass',y='Survived',hue='Sex',ci=None)
<matplotlib.axes._subplots.AxesSubplot at 0xb37d2800b8>
# 第二步,再用FacetGrid函数同时绘制不同年龄组的生还概率
sns.FacetGrid(data=titanic_df,row='Ageband',aspect=1.5)\
.map(sns.pointplot, 'Pclass','Survived','Sex',hue_order=['male','female'],palette='deep',ci=None)
9.综合考虑性别、舱位和登船码头与生还概率的关系
# 方法1:pivot_table
titanic_df.pivot_table(values='Survived',index=['Sex','Pclass','Embarked'],aggfunc=np.mean)
# 方法2:pivot_table
titanic_df.pivot_table(values='Survived',index=['Embarked','Pclass'],columns='Sex',aggfunc=np.mean)
# 方法3:画出折线图,我们尝试用一下上节课学到的pairplot函数,两两因素相匹配,按照年龄段来划分颜色
sns.pairplot(titanic_df, hue='Ageband')
# 方法4:用折线图体现性别、舱位和登船码头与生还概率的关系。
# 同样的,第一步先画出三个关系的折线图,我们先考虑性别、舱位和生还概率
sns.pointplot(data=titanic_df, x='Sex',y='Survived',hue='Pclass',ci=None)
# 第二步,使用FacetGrid函数
sns.FacetGrid(data = titanic_df, row='Embarked', aspect=1.5) \
.map(sns.pointplot, 'Sex', 'Survived', 'Pclass',hueorder=['male','female'], palette='deep', ci=None)
网友评论