面试题"/>
数据可视化面试题
问答题
1.随机从某超市抽取10个顾客,得到他们购物所花费的金额(单位:元)
-
数据:388,24,152,63.2,224.6,26,69,70,138,213
-
请问我们可以用哪些统计量,分析该组数据?
- 中心趋势统计量: median(均值), mean(中位数),mode(众数)
- 散布程度统计量:标准差(方差),四分位极差 (极差range=Max - Min 四分位极差(IQR)= Q3 - Q1)
- 分布形状统计量: 偏度系数和峰度系数
偏度是用于衡量数据分布对称性的统计量:通过对偏度系数的测量,我们能够判定数据分布的不对称程度以及方向。
对于正态分布(或严格对称分布)偏度等于0 若偏度为负, 则x均值左侧的离散度比右侧强; 若偏度为正, 则x均值左侧的离散度比右侧弱;
峰度是用于衡量数据分布陡峭或平滑的统计量,通过对峰度系数的测量,我们能够判定数据分布相对于正态分布而言是更陡峭还是平缓。
正态分布的峰度为3, 当时间序列的曲线峰值比正态分布的高时,峰度大于3; 当比正态分布的低时,峰度小于3。
(1)偏度系数
偏度系数反映数据分布偏移中心位置的程度,记为SK,则有 SK= (均值一中位数)/标准差。偏度系数是描述分布偏离对称性程度的一个特征数。
正态分布的偏度为0,偏度<0称分布具有负偏离(左偏态),此时数据位于均值左边的位于右边的多,有个尾巴拖到左边,说明左边有极端值,偏度>0称分布具有正偏离(右偏态)。偏度接近如于0 ,可认为分布对称。例如:知道分布有可能在偏度上偏离正态分布,则可用偏度来检验分布的正态性。偏度的绝对值数值越大表示其分布形态的偏斜程度越大。
(2)峰度系数
峰度系数(Kurtosis)用来度量数据在中心聚集程度,记为K,描述总体中所有取值分布形态陡缓程度的统计量(与正态分布比较,,就是正态分布的峰顶)。
例如:正态分布的峰度系数值是3,K>3的峰度系数说明观察量更集中,有比正态分布更短的尾部;K<3的峰度系数说明观测量不那么集中,有比正态分布更长的尾部。
2.(接上题)试从可视化的角度分别解读这些统计量刻画了数据分布的哪些特征?
- 集中趋势通过均值、中位数和众数来度量。
-
- 1,均值
-
- 均值是所有数据的平均值,使用mean()函数来计算向量的均值:
age.mean <- mean(Arthritis$Age)
- 均值是所有数据的平均值,使用mean()函数来计算向量的均值:
如果数据中存在极端值或者数据是偏态分布的,那么均值就不能很好地度量数据的集中趋势,为了消除少数极端值的影响,可以使用截断均值或者中位数来度量数据的集中趋势。截断均值是指去掉极端值之后的平均值。
-- 2,中位数 -- 中位数是把一组观察值从小到大按顺序排列,位于中间的那个数据。使用median(x)计算中位数。
age.median <- median(Arthritis$Age)
-- 3,众数
众数是指数据集中出现最频繁的值,众数常用于定性数据。R没有标准的内置函数来计算众数,
衡量离中趋势的四个度量值:
值域(Range)的计算公式:Range = Max - Min 标准差:度量数据偏离均值的程度 变异系数(CV):变异系数度量标准差相对于均值的离中趋势,计算公式是:CV=标准差/均值 四分位数间距(IQR)是上四分位数QU和下四分位数QL之差,其间包含全部观察值的一般,其值越大,说明数据的变异程度越大,离中趋势越明显。
3.下表是2006年北京上海和天津,按收入法计算的地区生产总值(按当年价格计算)数据。
地 区 | 劳动者报酬 | 生产税净额 | 固定资产折旧 | 营业盈余 |
---|---|---|---|---|
北京 | 3496.57 | 1161.55 | 1251.09 | 1961.07 |
天津 | 1383.36 | 775.09 | 595.09 | 1605.61 |
上海 | 3756.56 | 1623.36 | 1730.51 | 3255.94 |
- 请给出至少三种适用于描述上述数据所用的可视化图形?并简要说明这些方法的特点和用途。
- 曲线图:matplotlib.pyplot.plot(data)
- 灰度/直方图:matplotlib.pyplot.hist(data)
- 散点图:matplotlib.pyplot.scatter(data)
- 箱式/箱线图:matplotlib.pyplot.boxplot(data)
-- 直方图: (1)适用范围
直方图是针对连续型变量做的统计图。它最大的用途是观察数据分布的形态,了解数据的取值范围
(2) 注意事项
Ⅰ、直方图的横轴表示区间,这些区间可以是等距的,也可以是不等距的;可以是左开右闭的,也可以是左闭右开的;
Ⅱ、直方图最大的用处是观察数据分布的形态,了解数据的取值范围。关于数据分布,直方图可以分为对称、左偏、右偏。而直方图左偏还是右偏,与其尾巴往哪偏是一致的。
Ⅲ、对于连续型变量,为确定其分布,我们往往先画出它的直方图。但若画出的直方图不美观,建议不要放在PPT中,此时可用更加美观、有说服力的图表或文字来展示。
Ⅳ、直方图不能有效传递信息时,也建议用统计表或文字来展示。
Ⅴ、柱状图的横轴,可以是类,也可以是表示类别或者范围的数字,但真正有意义的是柱状图的高度。直方图的横轴表示一个范围与区间,直方图真正有意义的是它的面积。理论上来讲,在直方图中是可以画出粗细不同的图形,而这些图形也有所含义。但是在柱状图中,图形的粗细非但没有含义,而且也会影响美观。
Ⅵ、分析报告或PPT中的直方图,尽量避免柱高使用密度衡量,因为不易解释。 -- 散点图 (1)适用范围
用于展示两个连续型变量的一种常用统计图。
(2)注意事项
Ⅰ、从散点图可以解读两个变量的相关关系,其中包括正线性相关、负线性相关、非线性相关、不相关;
Ⅱ、相关关系不等于因果关系。人们渴求因果关系,但常用的许多统计工具(回归分析等),探求的只是相关关系;
Ⅲ、除了已知的两个变量,当数据中还有其他变量信息时,可以通过改变“点”的颜色、形状和大小来表达;
Ⅳ、从散点图上。还能发现一些“异常”的信息,也就是“离群点”;
Ⅴ、当数据中有多个连续变量时,可以两两画散点图“矩阵”。但是连续型变量过多,画散点图会导致无法抓住重点,此时可以用相关系数矩阵图来表示。
-- 箱线图 (1)适用范围
箱线图是一种针对连续型变量的统计图。它常用来配合定性变量画分组箱线图作比较。如果只有一个定量变量,很少用一个箱线图去展示其分布,此时更多选择直方图。
(3)注意事项
Ⅰ、箱线图的三要素:
其一、箱子的中间一条线是数据的中位数,代表了样本数据的平均水平;
其二、箱子的上下限,分别是数据的上四分位数和下四分位数,意味着箱子包含50%的数据。因此,箱子的高度在一定程度上反映了数据的波动程度;
其三、在箱子的上方和下方,各有一条线,分别代表上界和下界。对于冒出去的点,应理解为异常值。
Ⅱ、虽然箱线图也能看分布的形态,但人们更习惯从直方图去解读分布的形态。
4.试述有哪些方法可以判断一组数据是否服从正态分布?
- 描述统计方法
-
- 描述统计就是用描述的数字或图表来判断数据是否符合正态分布。常用的方法有Q-Q图、P-P图、直方图、茎叶图。
Q-Q图 Q是quantile的缩写,即分位数。 分位数就是将数据从小到大排序,然后切成100份,看不同位置处的值。比如中位数,就是中间位置的值。Q-Q图的x轴为分位数,y轴为分位数对应的样本值。x-y是散点图的形式,通过散点图可以拟合出一条直线, 如果这条直线的斜率为标准差,截距为均值.,则可以判断数据符合正态分布,否则则不可以。
P-P图 P-P图是根据变量的累积概率对应于所指定的理论分布累积概率绘制的散点图,用于直观地检测样本数据是否符合某一概率分布。如果被检验的数据符合所指定的分布,则代表样本数据的点应当基本在代表理论分布的对角线上。 P-P图的检验原理与Q-Q图基本相同,只是Q-Q图用的是分布的分位数来做检验,而P-P图是用分布的累计比。和Q-Q图一样,如果数据为正态分布,则在P-P正态分布图中,数据点应基本在图中对角线上。
直方图 直方图分为两种,一种是频率分布直方图,一种是频数分布直方图。频数就是样本值出现的次数,频率是某个值出现的次数与所有样本值出现总次数的比值。从直方图我们可以很直观的看出这组数据是否符合正态分布。
茎叶图 茎叶图的思路是将数组中的数按位数进行比较,将数的大小基本不变或变化不大的位作为一个主干(茎),将变化大的位的数作为分枝(叶),列在主干的后面,这样就可以清楚地看到每个主干后面的几个数,每个数具体是多少。 茎叶图是一个与直方图相类似的特殊工具,但又与直方图不同,茎叶图保留原始资料的资讯,直方图则失去原始资料的讯息。将茎叶图茎和叶逆时针方向旋转90度,实际上就是一个直方图,可以从中统计出次数,计算出各数据段的频率或百分比。从而可以看出分布是否与正态分布或单峰偏态分布逼近。
- 统计检验方法
讲完了描述统计的方法,我们来看一下统计检验的方法。统计检验的方法主要有SW检验、KS检验、AD检验、W检验。
- SW检验 SW检验中的S就是偏度,W就是峰度。 偏度(skewness),是统计数据分布偏斜方向和程度的度量,是统计数据分布非对称程度的数字特征。包括右偏分布(也叫正偏分布,其偏度>0),正态分布(偏度=0),左偏分布(也叫负偏分布,其偏度<0)。在定义上,偏度是样本的三阶标准化矩: 峰度(kurtosis),表征概率密度分布曲线在平均值处峰值高低的特征数。直观看来,峰度反映了峰部的尖度,计算方法为随机变量的四阶中心矩与方差平方的比值。公式上就是把偏度计算公式里的幂次改为4即可。峰度包括正态分布(峰度值=3),厚尾(峰度值>3),瘦尾(峰度值<3)。公式可表示如下:
在Python的scipy包中scipy.stats.normaltest(x, axis=0, nan_policy=‘propagate’)的原理就是基于数据的偏度和峰度,该方法是专门做正态性检验的。x:待检验的数据;axis:默认为0,表示在0轴上检验,即对数据的每一行做正态性检验,我们可以设置为 axis = None 来对整个数据做检验;nan_policy:当输入的数据中有空值时的处理办法。默认为 ‘propagate’,返回空值;设置为 ‘raise’ 时,抛出错误;设置为 ‘omit’ 时,在计算中忽略空值。
-
KS检验 KS检验是基于样本累积分布函数来进行判断的。可以用于判断某个样本集是否符合某个已知分布,也可以用于检验两个样本之间的显著性差异。如果是判断某个样本是否符合某个已知分布,比如正态分布,则需要先计算出标准正态分布的累计分布函数,然后计算样本集的累计分布函数。两个函数之间在不同的取值处会有不同的差值。我们只需要找出来差值最大的那个点D。然后基于样本集的样本数和显著性水平找到差值边界值(类似于t检验的边界值)。判断边界值和D的关系, 如果D小于边界值,则可以认为样本的分布符合已知分布,否则不可以。
-
AD检验 AD检验是在KS基础上进行改造的,KS检验只考虑了两个分布之间差值最大的那个点,但是这容易受异常值的影响。 AD检验考虑了分布上每个点处的差值。 在Python中可通过scipy包直接进行KS检验:scipy.stats.anderson(x, dist= ‘norm’),x为待检验的样本集,dist用来指明已知分布的类型,可选值与ks检验中可选值一致。返回三个结果: 第一个为统计值,第二个为评判值,第三个为每个评判值对应的显著性水平。
-
W检验 W检验(Shapiro-Wilk的简称)是基于两个分布的相关性来进行判断,会得出一个类似于皮尔逊相关系数的值。 值越大,说明两个分布越相关,越符合某个分布。 在Python中可通过scipy包直接进行W检验:scipy.stats.shapiro(x),x为待检验的样本集,上面的代码会返回两个结果:W值和其对应的p_value。shapiro是专门用于正态性检验的,所以不需要指明分布类型。且 shapiro 不适合做样本数>5000的正态性检验。
5.试述您对置信水平和置信区间的理解?
置信区间是一种常用的区间估计方法,所谓置信区间就是分别以统计量的置信上限和置信下限为上下界构成的区间 [2] 。对于一组给定的样本数据,其平均值为μ,标准偏差为σ,则其整体数据的平均值的100(1-α)%置信区间为(μ-Ζα/2σ , μ+Ζα/2σ) ,其中α为非置信水平在正态分布内的覆盖面积 ,Ζα/2即为对应的标准分数。 [1] 对于一组给定的数据,定义 为观测对象,W为所有可能的观测结果,X为实际上的观测值,那么X实际上是一个定义在 上,值域在W 上的随机变量。这时,置信区间的定义是一对函数u(.) 以及v(.) ,也就是说,对于某个观测值X=,其置信区间为 。实际上,若真实值为w,那么置信水平就是概率c:
其中U=u(X)和 V=v(X)都是统计量(即可观测的随机变量),而置信区间因此也是一个随机区间:(U,V)
置信区间与置信水平、样本量等因素均有关系,其中样本量对置信区间的影响为:在置信水平固定的情况下,样本量越多,置信区间越窄。其次,在样本量相同的情况下,置信水平越高,置信区间越宽。
1、在置信水平相同的情况下,样本量越多,置信区间越窄。 2、置信区间变窄的速度不像样本量增加的速度那么快,也就是说并不是样本量增加一倍,置信区间也变窄一半(实践证明,样本量要增加4倍,置信区间才能变窄一半),所以当样本量达到一个量时(通常是1,200),就不再增加样本了。故:置信区间=点估计 ±(关键值 × 点估计的标准差)。在其他因素不变的情况下,样本量越多(大),置信区间越窄(小)。
实战题(共四大题,20小题)
注意:每小题绘图均要求使用seaborn库进行,绘图下方均要求给出同学的分析或见解,只有图没有分析不给分
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
1.航班乘客变化分析 (10分)
- 载入相应绘图库及航班乘客数据(flights)
flights_df=sns.load_dataset("flights")
flights_df.head()
year | month | passengers | |
---|---|---|---|
0 | 1949 | Jan | 112 |
1 | 1949 | Feb | 118 |
2 | 1949 | Mar | 132 |
3 | 1949 | Apr | 129 |
4 | 1949 | May | 121 |
- 分析年度乘客总量变化情况(折线图)
data_number = flights_df.groupby(flights_df['year']).sum()
data_number
passengers | |
---|---|
year | |
1949 | 1520 |
1950 | 1676 |
1951 | 2042 |
1952 | 2364 |
1953 | 2700 |
1954 | 2867 |
1955 | 3408 |
1956 | 3939 |
1957 | 4421 |
1958 | 4572 |
1959 | 5140 |
1960 | 5714 |
plt.plot(data_number.index,data_number.values)
[<matplotlib.lines.Line2D at 0x247b95e68b0>]
- 分析乘客在一年中各月份的分布(柱状图)
data_number = flights_df[['month','passengers']].groupby(['month']).sum()
data_number = pd.Series(data_number['passengers'].values,index=(np.arange(1,13,1)))
data_number
1 2901 2 2820 3 3242 4 3205 5 3262 6 3740 7 4216 8 4213 9 3629 10 3199 11 2794 12 3142 dtype: int64
plt.bar(data_number.index,data_number.values)
<BarContainer object of 12 artists>
2.鸢尾花花型尺寸分析
- 载入iris数据集
iris_df=sns.load_dataset("iris")
iris_df.head()
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
- 萼片(sepal)和花瓣(petal)的大小关系(散点图)
iris_df['sepal_size'] = iris_df['sepal_length'] * iris_df['sepal_width']
iris_df['petal_size'] = iris_df['petal_length'] * iris_df['petal_width']
plt.scatter(iris_df['sepal_size'],iris_df['petal_size'])
<matplotlib.collections.PathCollection at 0x247b9792ee0>
- 不同种类鸢尾花萼片和花瓣大小的分布情况(柱状图或者箱式图)
柱状图
plt.figure(figsize=(20,20))
flag = 1
for name in iris_df.groupby(['species']).size().index:
sepal_size = iris_df[iris_df['species'].values == name]['sepal_size']
petal_size = iris_df[iris_df['species'].values == name]['petal_size']
plt.subplot(2,2,flag)
plt.bar(sepal_size.values,petal_size.values)
plt.title(name)
flag += 1
plt.show()
箱式图
plt.figure(figsize=(20,20))
flag = 1
for name in iris_df.groupby(['species']).size().index:
sepal_size = iris_df[iris_df['species'].values == name]['sepal_size']
petal_size = iris_df[iris_df['species'].values == name]['petal_size']
plt.subplot(3,3,flag)
plt.boxplot(sepal_size.values
,patch_artist = True
# 中位数线颜色
, medianprops = {'color': 'b'}
# 箱子颜色设置,color:边框颜色,facecolor:填充颜色
, boxprops = {'color': 'b', 'facecolor': 'r'}
# 猫须颜色whisker
, whiskerprops = {'color': 'r'}
# 猫须界限颜色whisker cap
, capprops = {'color': 'b'})
plt.title(name +'+sepal_size')
plt.subplot(3,3,flag * 2)
plt.boxplot(sepal_size.values,
patch_artist = True
# 中位数线颜色
, medianprops = {'color': 'b'}
# 箱子颜色设置,color:边框颜色,facecolor:填充颜色
, boxprops = {'color': 'b', 'facecolor': 'r'}
# 猫须颜色whisker
, whiskerprops = {'color': 'r'}
# 猫须界限颜色whisker cap
, capprops = {'color': 'b'})
plt.title(name +'+petal_size')
flag += 1
plt.show()
- 不同种类(species)鸢尾花萼片和花瓣的大小关系(分类散点子图)
t = iris_df.groupby(['species']).size()#3种
t.index
Index(['setosa', 'versicolor', 'virginica'], dtype='object', name='species')
iris_df[iris_df['species'].values == 'setosa']['sepal_size']
0 17.85 1 14.70 2 15.04 3 14.26 4 18.00 5 21.06 6 15.64 7 17.00 8 12.76 9 15.19 10 19.98 11 16.32 12 14.40 13 12.90 14 23.20 15 25.08 16 21.06 17 17.85 18 21.66 19 19.38 20 18.36 21 18.87 22 16.56 23 16.83 24 16.32 25 15.00 26 17.00 27 18.20 28 17.68 29 15.04 30 14.88 31 18.36 32 21.32 33 23.10 34 15.19 35 16.00 36 19.25 37 17.64 38 13.20 39 17.34 40 17.50 41 10.35 42 14.08 43 17.50 44 19.38 45 14.40 46 19.38 47 14.72 48 19.61 49 16.50 Name: sepal_size, dtype: float64
plt.figure()
flag = 1
for name in iris_df.groupby(['species']).size().index:
sepal_size = iris_df[iris_df['species'].values == name]['sepal_size']
petal_size = iris_df[iris_df['species'].values == name]['petal_size']
plt.subplot(2,2,flag)
plt.scatter(sepal_size.values,petal_size.values)
flag += 1
plt.show()
3.餐厅小费情况分析
- 载入tips数据集
%matplotlib inline
import matplotlib as mpl
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
tips_df=sns.load_dataset("tips")
tips_df.head()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
- 小费和总消费之间的关系(散点图)
plt.figure(figsize=(10,10))
plt.scatter(tips_df['total_bill'],tips_df['tip'],color = 'r')
<matplotlib.collections.PathCollection at 0x27ed4aa4e80>
- 男性顾客和女性顾客,谁更慷慨(分类箱式图)
sexs = np.unique(tips_df['sex'].values)
sex_money = []
for sex in sexs:
sex_money.append(tips_df[tips_df['sex'] == sex]['tip'].values)
sex_money
[array([1.01, 3.61, 5. , 3.02, 1.67, 3.5 , 2.75, 2.23, 3. , 3. , 2.45,3.07, 2.6 , 5.2 , 1.5 , 2.47, 1. , 3. , 3.14, 5. , 2.2 , 1.83,5.17, 1. , 4.3 , 3.25, 2.5 , 3. , 2.5 , 3.48, 4.08, 4. , 1. ,4. , 3.5 , 1.5 , 1.8 , 2.92, 1.68, 2.52, 4.2 , 2. , 2. , 2.83,1.5 , 2. , 3.25, 1.25, 2. , 2. , 2.75, 3.5 , 5. , 2.3 , 1.5 ,1.36, 1.63, 5.14, 3.75, 2.61, 2. , 3. , 1.61, 2. , 4. , 3.5 ,3.5 , 4.19, 5. , 2. , 2.01, 2. , 2.5 , 3.23, 2.23, 2.5 , 6.5 ,1.1 , 3.09, 3.48, 3. , 2.5 , 2. , 2.88, 4.67, 2. , 3. ]),array([ 1.66, 3.5 , 3.31, 4.71, 2. , 3.12, 1.96, 3.23, 1.71,1.57, 3. , 3.92, 3.71, 3.35, 4.08, 7.58, 3.18, 2.34,2. , 2. , 4.3 , 1.45, 2.5 , 3.27, 3.6 , 2. , 2.31,5. , 2.24, 2.54, 3.06, 1.32, 5.6 , 3. , 5. , 6. ,2.05, 3. , 2.5 , 1.56, 4.34, 3.51, 3. , 1.76, 6.73,3.21, 2. , 1.98, 3.76, 2.64, 3.15, 2.01, 2.09, 1.97,1.25, 3.08, 4. , 3. , 2.71, 3. , 3.4 , 5. , 2.03,2. , 4. , 5.85, 3. , 3. , 3.5 , 4.73, 4. , 1.5 ,3. , 1.5 , 1.64, 4.06, 4.29, 3.76, 3. , 4. , 2.55,5.07, 2.31, 2.5 , 2. , 1.48, 2.18, 1.5 , 2. , 6.7 ,5. , 1.73, 2. , 2.5 , 2. , 2.74, 2. , 2. , 5. ,2. , 3.5 , 2.5 , 2. , 3.48, 2.24, 4.5 , 10. , 3.16,5.15, 3.18, 4. , 3.11, 2. , 2. , 3.55, 3.68, 5.65,3.5 , 6.5 , 3. , 5. , 2. , 4. , 1.5 , 2.56, 2.02,4. , 1.44, 2. , 2. , 4. , 4. , 3.41, 3. , 2.03,2. , 5.16, 9. , 3. , 1.5 , 1.44, 2.2 , 1.92, 1.58,3. , 2.72, 2. , 3. , 3.39, 1.47, 3. , 1.25, 1. ,1.17, 5.92, 2. , 1.75])]
fig, ax = plt.subplots()
ax.boxplot(sex_money)
ax.set_xticklabels(sexs)
[Text(1, 0, 'Female'), Text(2, 0, 'Male')]
- 抽烟与否是否会对小费金额产生影响(分类箱式图)
smokers = np.unique(tips_df['smoker'].values)
smoker_tip = []
for smoker in smokers:
smoker_tip.append(tips_df[tips_df['smoker'] == smoker]['tip'].values)
smoker_tip
[array([1.01, 1.66, 3.5 , 3.31, 3.61, 4.71, 2. , 3.12, 1.96, 3.23, 1.71,5. , 1.57, 3. , 3.02, 3.92, 1.67, 3.71, 3.5 , 3.35, 4.08, 2.75,2.23, 7.58, 3.18, 2.34, 2. , 2. , 4.3 , 3. , 1.45, 2.5 , 3. ,2.45, 3.27, 3.6 , 2. , 3.07, 2.31, 5. , 2.24, 2.54, 3.06, 1.32,5.6 , 3. , 5. , 6. , 2.05, 3. , 2.5 , 2.6 , 5.2 , 1.56, 4.34,3.51, 1.5 , 6.73, 2.64, 3.15, 2.47, 2.01, 1.97, 3. , 2.2 , 1.25,4. , 3. , 2.71, 3.4 , 1.83, 2.03, 5.17, 2. , 4. , 5.85, 3. ,3.5 , 3.25, 1.5 , 4.08, 3.76, 3. , 1. , 4. , 2.55, 4. , 3.5 ,5.07, 1.5 , 1.8 , 2.92, 2.31, 1.68, 2.5 , 2. , 2.52, 4.2 , 1.48,2. , 2. , 2.18, 1.5 , 2.83, 1.5 , 2. , 3.25, 1.25, 2. , 2. ,2.75, 3.5 , 6.7 , 5. , 5. , 2.3 , 1.5 , 1.36, 1.63, 1.73, 2. ,2.5 , 2. , 2.74, 2. , 2. , 5.14, 5. , 3.75, 2.61, 2. , 3.5 ,2.5 , 2. , 2. , 3.48, 2.24, 4.5 , 5. , 1.44, 9. , 3. , 3. ,2.72, 3.39, 1.47, 1.25, 4.67, 5.92, 1.75, 3. ]),array([ 3. , 1.76, 3.21, 2. , 1.98, 3.76, 1. , 2.09, 3.14,5. , 3.08, 3. , 5. , 3. , 1. , 4.3 , 4.73, 4. ,1.5 , 3. , 2.5 , 3. , 2.5 , 3.48, 1.64, 4.06, 4.29,4. , 2. , 3. , 1.61, 2. , 10. , 3.16, 5.15, 3.18,4. , 3.11, 2. , 2. , 4. , 3.55, 3.68, 5.65, 3.5 ,6.5 , 3. , 3.5 , 2. , 3.5 , 4. , 1.5 , 4.19, 2.56,2.02, 4. , 2. , 5. , 2. , 2. , 4. , 2.01, 2. ,2.5 , 4. , 3.23, 3.41, 3. , 2.03, 2.23, 2. , 5.16,2.5 , 6.5 , 1.1 , 3. , 1.5 , 1.44, 3.09, 2.2 , 3.48,1.92, 1.58, 2.5 , 2. , 2.88, 2. , 3. , 3. , 1. ,1.17, 2. , 2. ])]
fig, ax = plt.subplots()
ax.boxplot(smoker_tip)
ax.set_xticklabels(smokers)
[Text(1, 0, 'No'), Text(2, 0, 'Yes')]
- 工作日和周末,什么时候顾客给的小费更慷慨(分类箱式图)
tips_df.groupby(tips_df['day']).size()
day Thur 62 Fri 19 Sat 87 Sun 76 dtype: int64
days = np.array(['workday','restday'])
day_tip = []
def change_day(tips_df):
for day in tips_df.values:
if day[4] == 'Sun':
day_tip.append(['restday',day[1]])
else:
day_tip.append(['workday',day[1]])
#
change_day(tips_df)
day_tip = pd.DataFrame(day_tip,columns=['day','tip'])
day_tip
day | tip | |
---|---|---|
0 | restday | 1.01 |
1 | restday | 1.66 |
2 | restday | 3.50 |
3 | restday | 3.31 |
4 | restday | 3.61 |
... | ... | ... |
239 | workday | 5.92 |
240 | workday | 2.00 |
241 | workday | 2.00 |
242 | workday | 1.75 |
243 | workday | 3.00 |
244 rows × 2 columns
day_tips = []
for day in days:
day_tips.append(day_tip[day_tip['day'] == day]['tip'].values)
day_tips
[array([ 3.35, 4.08, 2.75, 2.23, 7.58, 3.18, 2.34, 2. , 2. ,4.3 , 3. , 1.45, 2.5 , 3. , 2.45, 3.27, 3.6 , 2. ,3.07, 2.31, 5. , 2.24, 3. , 1.5 , 1.76, 6.73, 3.21,2. , 1.98, 3.76, 2.64, 3.15, 2.47, 1. , 2.01, 2.09,1.97, 3. , 3.14, 5. , 2.2 , 1.25, 3.08, 4. , 3. ,2.71, 3. , 3.4 , 1.83, 5. , 2.03, 5.17, 2. , 4. ,5.85, 3. , 3. , 3.5 , 1. , 4.3 , 3.25, 4.73, 4. ,1.5 , 3. , 1.5 , 2.5 , 3. , 2.5 , 3.48, 4.08, 1.64,4.06, 4.29, 3.76, 4. , 3. , 1. , 1.5 , 1.8 , 2.92,2.31, 1.68, 2.5 , 2. , 2.52, 4.2 , 1.48, 2. , 2. ,2.18, 1.5 , 2.83, 1.5 , 2. , 3.25, 1.25, 2. , 2. ,2. , 2.75, 3.5 , 6.7 , 5. , 5. , 2.3 , 1.5 , 1.36,1.63, 1.73, 2. , 1.61, 2. , 10. , 3.16, 4.19, 2.56,2.02, 4. , 1.44, 2. , 5. , 2. , 2. , 4. , 2.01,2. , 2.5 , 4. , 3.23, 3.41, 3. , 2.03, 2.23, 2. ,5.16, 9. , 2.5 , 6.5 , 1.1 , 3. , 1.5 , 1.44, 3.09,2.2 , 3.48, 1.92, 3. , 1.58, 2.5 , 2. , 3. , 2.72,2.88, 2. , 3. , 3.39, 1.47, 3. , 1.25, 1. , 1.17,4.67, 5.92, 2. , 2. , 1.75, 3. ]),array([1.01, 1.66, 3.5 , 3.31, 3.61, 4.71, 2. , 3.12, 1.96, 3.23, 1.71,5. , 1.57, 3. , 3.02, 3.92, 1.67, 3.71, 3.5 , 2.54, 3.06, 1.32,5.6 , 3. , 5. , 6. , 2.05, 3. , 2.5 , 2.6 , 5.2 , 1.56, 4.34,3.51, 4. , 2.55, 4. , 3.5 , 5.07, 2.5 , 2. , 2.74, 2. , 2. ,5.14, 5. , 3.75, 2.61, 2. , 3.5 , 2.5 , 2. , 2. , 3. , 3.48,2.24, 4.5 , 5.15, 3.18, 4. , 3.11, 2. , 2. , 4. , 3.55, 3.68,5.65, 3.5 , 6.5 , 3. , 5. , 3.5 , 2. , 3.5 , 4. , 1.5 ])]
fig, ax = plt.subplots()
ax.boxplot(day_tips)
ax.set_xticklabels(days)
[Text(1, 0, 'workday'), Text(2, 0, 'restday')]
- 午饭和晚饭,哪一顿顾客更愿意给小费(分类箱式图)
times = np.unique(tips_df['time'].values)
times
array(['Dinner', 'Lunch'], dtype=object)
time_tips = []
for time in times:
time_tips.append(tips_df[tips_df['time'] == time]['tip'].values)
time_tips
[array([ 1.01, 1.66, 3.5 , 3.31, 3.61, 4.71, 2. , 3.12, 1.96,3.23, 1.71, 5. , 1.57, 3. , 3.02, 3.92, 1.67, 3.71,3.5 , 3.35, 4.08, 2.75, 2.23, 7.58, 3.18, 2.34, 2. ,2. , 4.3 , 3. , 1.45, 2.5 , 3. , 2.45, 3.27, 3.6 ,2. , 3.07, 2.31, 5. , 2.24, 2.54, 3.06, 1.32, 5.6 ,3. , 5. , 6. , 2.05, 3. , 2.5 , 2.6 , 5.2 , 1.56,4.34, 3.51, 3. , 1.5 , 1.76, 6.73, 3.21, 2. , 1.98,3.76, 2.64, 3.15, 2.47, 1. , 2.01, 2.09, 1.97, 3. ,3.14, 5. , 2.2 , 1.25, 3.08, 3. , 3.5 , 1. , 4.3 ,3.25, 4.73, 4. , 1.5 , 3. , 1.5 , 2.5 , 3. , 2.5 ,3.48, 4.08, 1.64, 4.06, 4.29, 3.76, 4. , 3. , 1. ,4. , 2.55, 4. , 3.5 , 5.07, 2.5 , 2. , 2.74, 2. ,2. , 5.14, 5. , 3.75, 2.61, 2. , 3.5 , 2.5 , 2. ,2. , 3. , 3.48, 2.24, 4.5 , 1.61, 2. , 10. , 3.16,5.15, 3.18, 4. , 3.11, 2. , 2. , 4. , 3.55, 3.68,5.65, 3.5 , 6.5 , 3. , 5. , 3.5 , 2. , 3.5 , 4. ,1.5 , 3.41, 3. , 2.03, 2.23, 2. , 5.16, 9. , 2.5 ,6.5 , 1.1 , 3. , 1.5 , 1.44, 3.09, 3. , 2.72, 2.88,2. , 3. , 3.39, 1.47, 3. , 1.25, 1. , 1.17, 4.67,5.92, 2. , 2. , 1.75, 3. ]),array([4. , 3. , 2.71, 3. , 3.4 , 1.83, 5. , 2.03, 5.17, 2. , 4. ,5.85, 3. , 1.5 , 1.8 , 2.92, 2.31, 1.68, 2.5 , 2. , 2.52, 4.2 ,1.48, 2. , 2. , 2.18, 1.5 , 2.83, 1.5 , 2. , 3.25, 1.25, 2. ,2. , 2. , 2.75, 3.5 , 6.7 , 5. , 5. , 2.3 , 1.5 , 1.36, 1.63,1.73, 2. , 4.19, 2.56, 2.02, 4. , 1.44, 2. , 5. , 2. , 2. ,4. , 2.01, 2. , 2.5 , 4. , 3.23, 2.2 , 3.48, 1.92, 3. , 1.58,2.5 , 2. ])]
fig, ax = plt.subplots()
ax.boxplot(time_tips)
ax.set_xticklabels(times)
[Text(1, 0, 'Dinner'), Text(2, 0, 'Lunch')]
- 就餐人数是否会对慷慨度产生影响(分类箱式图)
size = np.unique(tips_df['size'].values)
size
array([1, 2, 3, 4, 5, 6], dtype=int64)
size_tips = []
for number in size:
size_tips.append(tips_df[tips_df['size'] == number]['tip'].values)
size_tips
[array([1. , 1.83, 1. , 1.92]),array([1.01, 3.31, 2. , 1.96, 3.23, 1.71, 1.57, 3.02, 3.92, 4.08, 2.75,2.23, 3.18, 2. , 2. , 4.3 , 3. , 1.45, 3. , 3.27, 2.54, 3.06,1.32, 3. , 5. , 3. , 2.5 , 2.6 , 1.56, 3.51, 1.5 , 1.76, 3.21,2. , 1.98, 2.47, 2.01, 2.09, 1.97, 3.14, 5. , 2.2 , 1.25, 3.08,3. , 2.71, 3. , 3.4 , 5. , 2.03, 2. , 4. , 5.85, 3. , 3. ,3.5 , 1. , 4.3 , 3.25, 4. , 1.5 , 3. , 1.5 , 2.5 , 3. , 3.48,4.08, 1.64, 4.06, 4.29, 3.76, 4. , 3. , 2.55, 3.5 , 1.5 , 1.8 ,2.31, 1.68, 2.5 , 2. , 2.52, 1.48, 2. , 2. , 1.5 , 2.83, 1.5 ,2. , 3.25, 1.25, 2. , 2. , 2. , 2.75, 3.5 , 2.3 , 1.5 , 1.63,1.73, 2. , 2.5 , 2. , 2.61, 2.5 , 2. , 3. , 2.24, 1.61, 2. ,3.16, 5.15, 3.18, 4. , 3.11, 2. , 2. , 4. , 3.55, 5.65, 3. ,1.5 , 4.19, 2.56, 2.02, 4. , 1.44, 2. , 2. , 2. , 2.01, 2. ,2.5 , 2.03, 2.23, 2.5 , 1.1 , 1.5 , 1.44, 2.2 , 3.48, 1.58, 2.5 ,2. , 2.72, 2.88, 3.39, 1.47, 3. , 1.25, 1. , 1.17, 2. , 2. ,1.75, 3. ]),array([ 1.66, 3.5 , 1.67, 3.71, 3.5 , 3.35, 3.6 , 2. , 3.07,2.31, 5. , 2.24, 2.05, 2.64, 3.15, 3. , 2.5 , 4. ,4. , 2.18, 1.36, 2.74, 2. , 3.48, 10. , 3.5 , 3.5 ,3.5 , 4. , 4. , 3.23, 3.41, 2. , 6.5 , 3. , 3. ,4.67, 5.92]),array([3.61, 4.71, 3.12, 5. , 3. , 7.58, 2.34, 2.5 , 2.45, 5.6 , 6. ,5.2 , 4.34, 3. , 6.73, 3.76, 4. , 5.17, 4.73, 5.07, 2.92, 2. ,2. , 3.75, 2. , 3.5 , 4.5 , 3.68, 6.5 , 5. , 4. , 3. , 5.16,9. , 3.09, 3. , 2. ]),array([5. , 5.14, 5. , 2. , 3. ]),array([4.2, 6.7, 5. , 5. ])]
fig, ax = plt.subplots()
ax.boxplot(size_tips)
ax.set_xticklabels(size)
[Text(1, 0, '1'),Text(2, 0, '2'),Text(3, 0, '3'),Text(4, 0, '4'),Text(5, 0, '5'),Text(6, 0, '6')]
- 性别+抽烟的组合因素对慷慨度的影响(分组柱状图)
group = tips_df.groupby([tips_df['sex'], tips_df['smoker']])
group_list = np.unique(group.size().index)
group_list
array([('Female', 'No'), ('Female', 'Yes'), ('Male', 'No'),('Male', 'Yes')], dtype=object)
tips_df['myindex']= tips_df.apply(lambda x:tuple([x[2],x[3]]),axis=1)
tips_df.head()
total_bill | tip | sex | smoker | day | time | size | myindex | |
---|---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 | (Female, No) |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 | (Male, No) |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 | (Male, No) |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 | (Male, No) |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 | (Female, No) |
data_sex_smoker = tips_df[['myindex','tip']]
data_sex_smoker.head()
myindex | tip | |
---|---|---|
0 | (Female, No) | 1.01 |
1 | (Male, No) | 1.66 |
2 | (Male, No) | 3.50 |
3 | (Male, No) | 3.31 |
4 | (Female, No) | 3.61 |
sex_smoker_tips = []
for group in group_list:
sex_smoker_tips.append(data_sex_smoker[data_sex_smoker['myindex'] == group]['tip'].values)
sex_smoker_tips
[array([1.01, 3.61, 5. , 3.02, 1.67, 3.5 , 2.75, 2.23, 3. , 3. , 2.45,3.07, 2.6 , 5.2 , 1.5 , 2.47, 3. , 2.2 , 1.83, 5.17, 3.25, 4.08,1. , 4. , 3.5 , 1.5 , 1.8 , 2.92, 1.68, 2.52, 4.2 , 2. , 2. ,2.83, 1.5 , 2. , 3.25, 1.25, 2. , 2. , 2.75, 3.5 , 5. , 2.3 ,1.5 , 1.36, 1.63, 5.14, 3.75, 2.61, 2. , 3. , 4.67, 3. ]),array([1. , 3.14, 5. , 1. , 4.3 , 2.5 , 3. , 2.5 , 3.48, 4. , 3. ,1.61, 2. , 4. , 3.5 , 3.5 , 4.19, 5. , 2. , 2.01, 2. , 2.5 ,3.23, 2.23, 2.5 , 6.5 , 1.1 , 3.09, 3.48, 2.5 , 2. , 2.88, 2. ]),array([1.66, 3.5 , 3.31, 4.71, 2. , 3.12, 1.96, 3.23, 1.71, 1.57, 3. ,3.92, 3.71, 3.35, 4.08, 7.58, 3.18, 2.34, 2. , 2. , 4.3 , 1.45,2.5 , 3.27, 3.6 , 2. , 2.31, 5. , 2.24, 2.54, 3.06, 1.32, 5.6 ,3. , 5. , 6. , 2.05, 3. , 2.5 , 1.56, 4.34, 3.51, 6.73, 2.64,3.15, 2.01, 1.97, 1.25, 4. , 3. , 2.71, 3.4 , 2.03, 2. , 4. ,5.85, 3. , 3.5 , 1.5 , 3.76, 3. , 4. , 2.55, 5.07, 2.31, 2.5 ,2. , 1.48, 2.18, 1.5 , 6.7 , 5. , 1.73, 2. , 2.5 , 2. , 2.74,2. , 2. , 5. , 2. , 3.5 , 2.5 , 2. , 3.48, 2.24, 4.5 , 5. ,1.44, 9. , 3. , 2.72, 3.39, 1.47, 1.25, 5.92, 1.75]),array([ 3. , 1.76, 3.21, 2. , 1.98, 3.76, 2.09, 3.08, 3. ,5. , 3. , 4.73, 4. , 1.5 , 3. , 1.64, 4.06, 4.29,2. , 10. , 3.16, 5.15, 3.18, 4. , 3.11, 2. , 2. ,3.55, 3.68, 5.65, 3.5 , 6.5 , 3. , 2. , 4. , 1.5 ,2.56, 2.02, 4. , 2. , 2. , 4. , 4. , 3.41, 3. ,2.03, 2. , 5.16, 3. , 1.5 , 1.44, 2.2 , 1.92, 1.58,2. , 3. , 3. , 1. , 1.17, 2. ])]
fig, ax = plt.subplots()
ax.boxplot(sex_smoker_tips)
ax.set_xticklabels(group_list)
[Text(1, 0, "('Female', 'No')"),Text(2, 0, "('Female', 'Yes')"),Text(3, 0, "('Male', 'No')"),Text(4, 0, "('Male', 'Yes')")]
4.泰坦尼克号海难幸存状况分析
- 载入数据集
%matplotlib inline
import matplotlib as mpl
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
titanic_df=sns.load_dataset("titanic")
titanic_df.head()
# 幸存与否,仓位等级,性别,年龄,堂兄弟姐妹数,父母子女数,票价,上船港口缩写,仓位等级,人员分类,是否成年男性,所在甲板,上船港口,是否幸存,是否单独乘船
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 1 | 0 | 7.2500 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.0 | 1 | 0 | 71.2833 | C | First | woman | False | C | Cherbourg | yes | False |
2 | 1 | 3 | female | 26.0 | 0 | 0 | 7.9250 | S | Third | woman | False | NaN | Southampton | yes | True |
3 | 1 | 1 | female | 35.0 | 1 | 0 | 53.1000 | S | First | woman | False | C | Southampton | yes | False |
4 | 0 | 3 | male | 35.0 | 0 | 0 | 8.0500 | S | Third | man | True | NaN | Southampton | no | True |
- 不同仓位等级中幸存和遇难的乘客比例(堆积柱状图)
survived_pclass= titanic_df[['survived', 'pclass']].groupby(['survived','pclass']).size()
survived_pclass = survived_pclass.unstack(level=0)
survived_pclass
survived | 0 | 1 |
---|---|---|
pclass | ||
1 | 80 | 136 |
2 | 97 | 87 |
3 | 372 | 119 |
survived_pclass['total'] = survived_pclass[0] + survived_pclass[1]
survived_pclass['yes_prop'] = survived_pclass[1] / survived_pclass['total']
survived_pclass['no_prop'] = survived_pclass[0] / survived_pclass['total']
survived_pclass
survived | 0 | 1 | total | yes_prop | no_prop |
---|---|---|---|---|---|
pclass | |||||
1 | 80 | 136 | 216 | 0.629630 | 0.370370 |
2 | 97 | 87 | 184 | 0.472826 | 0.527174 |
3 | 372 | 119 | 491 | 0.242363 | 0.757637 |
# 绘制堆积柱状图
def stackedbarplot(x_data, y_data_list, y_data_names, colors, x_label, y_label, title):
_, ax = plt.subplots()
# 循环绘制堆积柱状图
for i in range(0, len(y_data_list)):
if i == 0:
ax.bar(x_data, y_data_list[i], color = colors[i], align = 'center', label = y_data_names[i])
else:
# 采用堆积的方式,除了第一个分类,后面的分类都从前一个分类的柱状图接着画
# 用归一化保证最终累积结果为1
ax.bar(x_data, y_data_list[i], color = colors[i], bottom = y_data_list[i - 1], align = 'center', label = y_data_names[i])
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'upper right') # 设定图例位置
# 调用绘图函数
stackedbarplot(x_data = survived_pclass.index.values
, y_data_list = [survived_pclass['yes_prop'], survived_pclass['no_prop']]
, y_data_names = ['Survived', 'Not survived']
, colors = ['#539caf', '#7663b0']
, x_label = 'pclass'
, y_label = 'Survival rate'
, title = 'pclass and Survival Rate')
- 不同性别的幸存比例(堆积柱状图)
sex_survived=titanic_df.groupby(['sex','survived']).size().unstack()
sex_survived
survived | 0 | 1 |
---|---|---|
sex | ||
female | 81 | 233 |
male | 468 | 109 |
sex_survived['sum']=sex_survived[0]+sex_survived[1]
sex_survived['yes_prop']=sex_survived[1]/sex_survived['sum']
sex_survived['no_prop']=sex_survived[0]/sex_survived['sum']
sex_survived
survived | 0 | 1 | sum | yes_prop | no_prop |
---|---|---|---|---|---|
sex | |||||
female | 81 | 233 | 314 | 0.742038 | 0.257962 |
male | 468 | 109 | 577 | 0.188908 | 0.811092 |
# 调用绘图函数
stackedbarplot(x_data = [0,1]
, y_data_list = [sex_survived['yes_prop'], sex_survived['no_prop']]
, y_data_names = ['Survived', 'Not survived']
, colors = ['#539caf', '#7663b0']
, x_label = 'Sex'
, y_label = 'Survival rate'
, title = 'Sex and Survival Rate')
- 幸存和遇难乘客的票价分布(分类箱式图)
def boxplot(x_data, y_data, base_color, median_color, x_label, y_label, title):
_, ax = plt.subplots()
ax.boxplot(y_data
# 箱子是否颜色填充
, patch_artist = True
# 中位数线颜色
, medianprops = {'color': base_color}
# 箱子颜色设置,color:边框颜色,facecolor:填充颜色
, boxprops = {'color': base_color, 'facecolor': median_color}
# 猫须颜色whisker
, whiskerprops = {'color': median_color}
# 猫须界限颜色whisker cap
, capprops = {'color': base_color})
# 箱图与x_data保持一致
ax.set_xticklabels(x_data)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
survived=titanic_df['survived'].unique()
bp_data=[titanic_df[titanic_df['survived']==survived[0]]['fare'],titanic_df[titanic_df['survived']==survived[1]]['fare']]
# 调用绘图函数
boxplot(x_data = survived
, y_data = bp_data
, base_color = 'b'
, median_color = 'r'
, x_label = 'survived'
, y_label = 'fare'
, title = 'Distribution of Fare By Survived')
- 幸存和遇难乘客的年龄分布(分类箱式图)
titanic_df['age'].fillna(0,inplace=True)
survived=titanic_df['survived'].unique()
bp_data=[titanic_df[titanic_df['survived']==survived[0]]['age'],titanic_df[titanic_df['survived']==survived[1]]['age']]
# 调用绘图函数
boxplot(x_data=survived
, y_data = bp_data
, base_color = 'b'
, median_color = 'r'
, x_label = 'survived'
, y_label = 'age'
, title = 'Distribution of Age By Survived')
- 不同上船港口的乘客仓位等级分布(分组柱状图)
embark_pclass=titanic_df.groupby(['embark_town','pclass']).size().unstack()
embark_pclass.fillna(0,inplace=True)
embark_pclass
pclass | 1 | 2 | 3 |
---|---|---|---|
embark_town | |||
Cherbourg | 85 | 17 | 66 |
Queenstown | 2 | 3 | 72 |
Southampton | 127 | 164 | 353 |
pclass_list=[embark_pclass.iloc[:,0],embark_pclass.iloc[:,1],embark_pclass.iloc[:,2]]
pclass_list
[embark_townCherbourg 85Queenstown 2Southampton 127Name: 1, dtype: int64,embark_townCherbourg 17Queenstown 3Southampton 164Name: 2, dtype: int64,embark_townCherbourg 66Queenstown 72Southampton 353Name: 3, dtype: int64]
# 绘制分组柱状图的函数
def groupedbarplot(x_data, y_data_list, y_data_names, colors, x_label, y_label,title):
_, ax = plt.subplots()
# 设置每一组柱状图的宽度
total_width = 0.8
# 设置每一个柱状图的宽度
ind_width = total_width / len(y_data_list)
# 计算每一个柱状图的中心偏移
alteration = np.arange(-total_width/2+ind_width/2, total_width/2+ind_width/2, ind_width)
# 分别绘制每一个柱状图
for i in range(0, len(y_data_list)):
# 横向散开绘制
ax.bar(x_data + alteration[i], y_data_list[i], color = colors[i], label = y_data_names[i], width = ind_width)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'upper right')
# 调用绘图函数
groupedbarplot(x_data = range(3)
, y_data_list = pclass_list
, y_data_names = embark_pclass.columns
, colors = ['#539caf', '#7663b0','#00ff00']
, x_label = 'embark_town'
, y_label = 'counts of pclass'
,title = 'Counts of Pclass vs Embark Town')
ax=plt.gca()
ax.set_xticks(range(3))
ax.set_xticklabels(embark_pclass.index.values)
[Text(0, 0, 'Cherbourg'), Text(1, 0, 'Queenstown'), Text(2, 0, 'Southampton')]
- 幸存和遇难乘客堂兄弟姐妹的数量分布(分类箱式图)
survived=titanic_df['survived'].unique()
bp_data=[titanic_df[titanic_df['survived']==survived[0]]['sibsp'],titanic_df[titanic_df['survived']==survived[1]]['sibsp']]
# 调用绘图函数
boxplot(x_data=survived
, y_data = bp_data
, base_color = 'b'
, median_color = 'r'
, x_label = 'survived'
, y_label = 'sibsp'
, title = 'Distribution of Sibsp By Survived')
- 幸存和遇难乘客父母子女的数量分布(分类箱式图)
survived=titanic_df['survived'].unique()
bp_data=[titanic_df[titanic_df['survived']==survived[0]]['parch'],titanic_df[titanic_df['survived']==survived[1]]['parch']]
# 调用绘图函数
boxplot(x_data=survived
, y_data = bp_data
, base_color = 'b'
, median_color = 'r'
, x_label = 'survived'
, y_label = 'parch'
, title = 'Distribution of Parch By Survived')
单独乘船与否和幸存之间有没有联系(堆积柱状图或者分组柱状图)
alone_survived=titanic_df.groupby(['alone','survived']).size().unstack()
alone_survived
survived | 0 | 1 |
---|---|---|
alone | ||
False | 175 | 179 |
True | 374 | 163 |
_, ax = plt.subplots()
width=0.4
index=alone_survived.index.values
ax.bar(index, alone_survived[0], color = '#ff0000', label = 'Not survived', width = width)
ax.bar(index+width, alone_survived[1], color = '#00ff00', label = 'Survived', width = width)
ax.set_ylabel('numbers of People')
ax.set_xlabel('alone')
ax.set_title('People Survived vs Alone')
ax.legend(loc = 'upper right')
plt.xticks(index+width,index)
([<matplotlib.axis.XTick at 0x27ed66ea7c0>,<matplotlib.axis.XTick at 0x27ed66eadf0>],[Text(0.4, 0, 'False'), Text(1.4, 0, 'True')])
更多推荐
数据可视化面试题
发布评论