复习:在前面我们已经学习了Pandas基础,第二章我们开始进入数据分析的业务部分,在第二章第一节的内容中,我们学习了数据的清洗,这一部分十分重要,只有数据变得相对干净,我们之后对数据的分析才可以更有力。而这一节,我们要做的是数据重构,数据重构依旧属于数据理解(准备)的范围。
# 导入基本库
import numpy as np
import pandas as pd
# 载入data文件中的:train-left-up.csv
df = pd.read_csv('DataWhale教程/data/train-left-up.csv')
df.head()
PassengerId | Survived | Pclass | Name | |
---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) |
4 | 5 | 0 | 3 | Allen, Mr. William Henry |
# 四个边角的数据
left_up = pd.read_csv("DataWhale教程/data/train-left-up.csv")
left_down = pd.read_csv("DataWhale教程/data/train-left-down.csv")
right_up = pd.read_csv("DataWhale教程/data/train-right-up.csv")
right_down = pd.read_csv("DataWhale教程/data/train-right-down.csv")
left_up.head()
PassengerId | Survived | Pclass | Name | |
---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) |
4 | 5 | 0 | 3 | Allen, Mr. William Henry |
left_down.head()
PassengerId | Survived | Pclass | Name | |
---|---|---|---|---|
0 | 440 | 0 | 2 | Kvillner, Mr. Johan Henrik Johannesson |
1 | 441 | 1 | 2 | Hart, Mrs. Benjamin (Esther Ada Bloomfield) |
2 | 442 | 0 | 3 | Hampe, Mr. Leon |
3 | 443 | 0 | 3 | Petterson, Mr. Johan Emil |
4 | 444 | 1 | 2 | Reynaldo, Ms. Encarnacion |
right_down.head()
Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|
0 | male | 31.0 | 0 | 0 | C.A. 18723 | 10.500 | NaN | S |
1 | female | 45.0 | 1 | 1 | F.C.C. 13529 | 26.250 | NaN | S |
2 | male | 20.0 | 0 | 0 | 345769 | 9.500 | NaN | S |
3 | male | 25.0 | 1 | 0 | 347076 | 7.775 | NaN | S |
4 | female | 28.0 | 0 | 0 | 230434 | 13.000 | NaN | S |
right_up.head()
Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|
0 | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
【提示】结合之前我们加载的train.csv数据,大致预测一下上面的数据是什么
# 将左上和右上合并
result_up = pd.concat([left_up,right_up],axis=1)
result_up.head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
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 |
# 将左下和右下合并
result_down = pd.concat([left_down,right_down],axis=1)
# 将完整的上和下进行纵向合并
result = pd.concat([result_up,result_down],axis=0)
result.shape
(891, 12)
resul_up = left_up.join(right_up) # 左右合并
result_down = left_down.join(right_down) # 左右合并
result = result_up.append(result_down) # 上下合并
result.shape
(891, 12)
# 设置参数使其使用行索引进行拼接
result_up = pd.merge(left_up,right_up,left_index=True,right_index=True)
result_down = pd.merge(left_down,right_down,left_index=True,right_index=True)
result = resul_up.append(result_down)
result.shape
(891, 12)
【思考】对比merge、join以及concat的方法的不同以及相同。思考一下在任务四和任务五的情况下,为什么都要求使用DataFrame的append方法,如何只要求使用merge或者join可不可以完成任务四和任务五呢?
merge和join类似 横向合并列 左右合并
感觉使用concat和join+append比merge方便
result.to_csv('result.csv')
这个stack函数是干什么的?
返回一个重构的数据。把列转置为行
# 将完整的数据加载出来
data = pd.read_csv('result.csv')
data.head()
Unnamed: 0 | PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
data.stack().head(30)
# 将原先每一行代表的一个乘客的所有数据 转置为 一列为一个用户的所有数据
0 Unnamed: 0 0
PassengerId 1
Survived 0
Pclass 3
Name Braund, Mr. Owen Harris
Sex male
Age 22
SibSp 1
Parch 0
Ticket A/5 21171
Fare 7.25
Embarked S
1 Unnamed: 0 1
PassengerId 2
Survived 1
Pclass 1
Name Cumings, Mrs. John Bradley (Florence Briggs Th...
Sex female
Age 38
SibSp 1
Parch 0
Ticket PC 17599
Fare 71.2833
Cabin C85
Embarked C
2 Unnamed: 0 2
PassengerId 3
Survived 1
Pclass 3
Name Heikkinen, Miss. Laina
dtype: object
#将代码保存为unit_result,csv
data.to_csv('unit_result.csv')
test = pd.read_csv('unit_result.csv')
test.head()
Unnamed: 0 | Unnamed: 0.1 | PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 1 | 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 2 | 2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 3 | 3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 4 | 4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
# 导入基本库
import numpy as np
import pandas as pd
# 载入data文件中的:result.csv
df = pd.read_csv('result.csv')
df.head()
Unnamed: 0 | PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
使用groupby可以对数据集进行切片、切块、摘要等操作
拆分 - 应用 - 合并
先将数据集中相同的key进行拆分汇总 再应用运算 最后合并结果(适用于series数据类型)
应用(聚合操作)
在了解GroupBy机制之后,运用这个机制完成一系列的操作,来达到我们的目的。
下面通过几个任务来熟悉GroupBy机制。
# 将票价根据性别分类 并查看描述性统计数据
# df['Fare'].groupby(df['Sex']).describe()
mean_fare_sex=df['Fare'].groupby(df['Sex']).mean()
mean_fare_sex
Sex
female 44.479818
male 25.523893
Name: Fare, dtype: float64
# 将存活人数根据性别分类后算总和
survived_sex = df['Survived'].groupby(df['Sex']).sum()
survived_sex
Sex
female 233
male 109
Name: Survived, dtype: int64
# 将存活人数根据客舱等级分类后求和
survived_pclass = df['Survived'].groupby(df['Pclass']).sum()
survived_pclass
Pclass
1 136
2 87
3 119
Name: Survived, dtype: int64
【提示:】表中的存活那一栏,可以发现如果还活着记为1,死亡记为0
【思考:】从数据分析的角度,上面的统计结果可以得出那些结论
#思考心得
【思考】从任务二到任务三中,这些运算可以通过agg()函数来同时计算。并且可以使用rename函数修改列名。你可以按照提示写出这个过程吗?
上述使用到的聚合操作只能单一,当我们需要分类的事物(key)相同,分类的数据(列)不同时,可以使用agg()字典的方式自定义多个聚合操作(指定列)使用统一的分类key来进行运算
并可以使用rename操作重命名列名,相当于分别进行独立聚合操作后 合并数据
# 例:
# 根据性别分类 计算票价的平均值,存活的总数
df.groupby('Sex').agg({'Fare': 'mean', 'Survived': 'sum'}).rename(columns=
{'Fare': 'mean_fare', 'Survived': 'count_survived'})
mean_fare | count_survived | |
---|---|---|
Sex | ||
female | 44.479818 | 233 |
male | 25.523893 | 109 |
# 将票价按照客舱等级分类 相同的客舱等级按年龄分类 计算不同年龄船票的平均值
df.groupby(['Pclass','Age'])['Fare'].mean().head()
Pclass Age
1 0.92 151.550000
2.00 151.550000
4.00 81.858300
11.00 120.000000
14.00 120.000000
...
2 23.00 12.833929
24.00 27.425000
25.00 23.225600
26.00 18.250000
27.00 16.226383
Name: Fare, Length: 80, dtype: float64
# 将两数据合并,使用同一 行index 'Sex'
sex_fare_survived = pd.merge(mean_fare_sex,survived_sex,on='Sex')
sex_fare_survived
# ??? 视频提到要merge要转换为dataframe才行,series不行 但是这里合并成功了
Fare | Survived | |
---|---|---|
Sex | ||
female | 44.479818 | 233 |
male | 25.523893 | 109 |
result.to_csv('sex_fare_survived.csv')
#不同年龄的存活人数
# 将存活按照年龄分类 统计不同年龄的存活数
survived_age = df['Survived'].groupby(df['Age']).sum()
survived_age
Age
0.42 1
0.67 1
0.75 2
0.83 2
0.92 1
..
70.00 0
70.50 0
71.00 0
74.00 0
80.00 1
Name: Survived, Length: 88, dtype: int64
#找出最大值的年龄段
# 通过索引表达式 直接索引出最大存活的年龄
survived_age[survived_age.values==max(survived_age)]
Age
24.0 15
Name: Survived, dtype: int64
# 最大年龄段的最大存活率为 年龄段中存活人数最高的人数/总存活人数
precetn =survived_age.max()/df['Survived'].sum()
print("最大存活率:"+str(precetn))
最大存活率:0.043859649122807015
**复习:**回顾学习完第一章,我们对泰坦尼克号数据有了基本的了解,也学到了一些基本的统计方法,第二章中我们学习了数据的清理和重构,使得数据更加的易于理解;今天我们要学习的是第二章第三节:数据可视化,主要给大家介绍一下Python数据可视化库Matplotlib,在本章学习中,你也许会觉得数据很有趣。在打比赛的过程中,数据可视化可以让我们更好的看到每一个关键步骤的结果如何,可以用来优化方案,是一个很有用的技巧。
# 加载所需的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
导入result.csv这个文件
df = pd.read_csv('result.csv')
df.head()
Unnamed: 0 | PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
《Python for Data Analysis》第九章
【思考】最基本的可视化图案有哪些?分别适用于那些场景?(比如折线图适合可视化某个属性值随时间变化的走势)
思考回答
%matplotlib inline
# 把存活根据性别分类 并计数
sex = df.groupby('Sex')['Survived'].sum()
# 柱状图
sex.plot.bar()
plt.title('survived_count')
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6nxlGvPb-1647710778053)(output_72_0.png)]
【思考】计算出泰坦尼克号数据集中男女中死亡人数,并可视化展示?如何和男女生存人数可视化柱状图结合到一起?看到你的数据可视化,说说你的第一感受(比如:你一眼看出男生存活人数更多,那么性别可能会影响存活率)。
# 提示:计算男女中死亡人数 1表示生存,0表示死亡
# 根据性别分类 再根据性别的是否活着分类 统计死活的个数
print(df.groupby(['Sex','Survived'])['Survived'].count())
print(df.groupby(['Sex','Survived'])['Survived'].count().unstack())
sex_survived = df.groupby(['Sex','Survived'])['Survived'].count().unstack()
Sex Survived
female 0 81
1 233
male 0 468
1 109
Name: Survived, dtype: int64
Survived 0 1
Sex
female 81 233
male 468 109
died = sex_survived[0]
died.plot.bar()
plt.title('died')
Text(0.5, 1.0, 'died')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WdBUPQJ-1647710778054)(output_77_1.png)]
sex_survived.plot.bar()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-99MdrkP5-1647710778055)(output_78_1.png)]
sex_survived.plot(kind='bar',stacked='True')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQzM2AQY-1647710778055)(output_79_1.png)]
【提示】男女这两个数据轴,存活和死亡人数按比例用柱状图表示
【提示】对于这种统计性质的且用折线表示的数据,你可以考虑将数据排序或者不排序来分别表示。看看你能发现什么?
# 计算不同票价中生存与死亡人数 1表示生存,0表示死亡
# 先按票价分类 再按不同的票价里存活分类,再给存活计数 最后转置
fare = df.groupby(['Fare','Survived'])['Survived'].count().unstack()
fare
Survived | 0 | 1 |
---|---|---|
Fare | ||
0.0000 | 14.0 | 1.0 |
4.0125 | 1.0 | NaN |
5.0000 | 1.0 | NaN |
6.2375 | 1.0 | NaN |
6.4375 | 1.0 | NaN |
... | ... | ... |
227.5250 | 1.0 | 3.0 |
247.5208 | 1.0 | 1.0 |
262.3750 | NaN | 2.0 |
263.0000 | 2.0 | 2.0 |
512.3292 | NaN | 3.0 |
248 rows × 2 columns
# plot 默认折线图
# 纵轴为存活个数
# 横轴为票价
fare.plot()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZWjmK8G-1647710778055)(output_84_1.png)]
# 1表示生存,0表示死亡
# 先给仓位排序 看死亡的个数
pclass=df.groupby(['Pclass','Survived'])['Survived'].count().unstack()
pclass
Survived | 0 | 1 |
---|---|---|
Pclass | ||
1 | 80 | 136 |
2 | 97 | 87 |
3 | 372 | 119 |
pclass.plot.bar()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kEThvUD-1647710778056)(output_87_1.png)]
【思考】看到这个前面几个数据可视化,说说你的第一感受和你的总结
思考题回答
# df.Survived == 0
df.Survived == 0 #返回一个bool列表
df['Age'][df.Survived==0] #指定列,传入行索引
df.Age[df.Survived==0]
# 以上两个写法相同
# 画直方图 hits 分段 bins 透明度 alpha
# 段数越少 年龄段内的死亡人数越多 死亡人数直方图
df.Age[df.Survived==0].hist(bins=4,alpha=0.5)# 死亡人数直方图
df.Age[df.Survived==1].hist(bins=4,alpha=0.5)# 生存人数直方图
# 添加图例
plt.legend((0,1))
plt.xlabel('age')
plt.ylabel('count')
Text(0, 0.5, 'count')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VoLxhn5h-1647710778057)(output_91_1.png)]
发现年龄小的存活数比年纪大的要大
# 根据分布密度画直方图
# 画直方图 hits 分段 bins 透明度 alpha 密度直方图 density
df.Age[df.Survived==0].hist(bins=4,alpha=0.5,density=1)# 死亡人数直方图
df.Age[df.Survived==1].hist(bins=4,alpha=0.5,density=1)# 生存人数直方图
# 添加密度曲线
df.Age[df.Survived==1].plot.density()
df.Age[df.Survived==0].plot.density()
# 添加图例 横纵坐标
plt.legend((0,1))
plt.xlabel('age')
plt.ylabel('density')
Text(0, 0.5, 'density')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JFh0zfHa-1647710778058)(output_93_1.png)]
# 存储仓位等级
unique_pclass=df.Pclass.unique()
unique_pclass.sort()
unique_pclass
array([1, 2, 3])
# 遍历
for i in unique_pclass:
df.Age[df.Pclass==i].plot.density()
plt.xlabel('age')
plt.legend(unique_pclass)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1LFKZ58-1647710778058)(output_96_1.png)]
import seaborn as sns
for i in unique_pclass:
sns.kdeplot(df.Age[df.Pclass==i],shade=True,linewidth=0.1)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oJGlp60h-1647710778059)(output_97_0.png)]
【思考】上面所有可视化的例子做一个总体的分析,你看看你能不能有自己发现
#思考题回答
【总结】到这里,我们的可视化就告一段落啦,如果你对数据可视化极其感兴趣,你还可以了解一下其他可视化模块,如:pyecharts,bokeh等。
如果你在工作中使用数据可视化,你必须知道数据可视化最大的作用不是炫酷,而是最快最直观的理解数据要表达什么,你觉得呢?