数据科学 2、分类盒须图,堆叠柱形图、stack2dim函数
方便自己查阅与新手学习,附上代码与数据。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import seaborn as sns
import os
画两个维度标准化的堆积柱状图函数
- 使用效果如下
stack2dim(auto,'Owner','loss_flag')
stack2dim(auto,'AntiTFD','loss_flag')
stack2dim(auto,'import','loss_flag')
stack2dim函数
# 如遇中文显示问题可加入以下代码
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
def stack2dim(raw, i, j, rotation=0, location='upper right'):
'''
此函数是为了画两个维度标准化的堆积柱状图
raw为pandas的DataFrame数据框
i、j为两个分类变量的变量名称,要求带引号,比如"school"
rotation:水平标签旋转角度,默认水平方向,如标签过长,可设置一定角度,比如设置rotation = 40
location:分类标签的位置,如果被主体图形挡住,可更改为'upper left'
'''
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import math
data_raw = pd.crosstab(raw[i], raw[j])
data = data_raw.div(data_raw.sum(1), axis=0) # 交叉表转换成比率,为得到标准化堆积柱状图
# 计算x坐标,及bar宽度
createVar = locals()
x = [0] # 每个bar的中心x轴坐标
width = [] # bar的宽度
k = 0
for n in range(len(data)):
# 根据频数计算每一列bar的宽度
createVar['width' + str(n)] = list(data_raw.sum(axis=1))[n] / sum(data_raw.sum(axis=1))
width.append(createVar['width' + str(n)])
if n == 0:
continue
else:
k += createVar['width' + str(n - 1)] / 2 + createVar['width' + str(n)] / 2 + 0.05
x.append(k)
# 以下是通过频率交叉表矩阵生成一串对应堆积图每一块位置数据的数组,再把数组转化为矩阵
y_mat = []
n = 0
y_level = len(data.columns)
for p in range(data.shape[0]):
for q in range(data.shape[1]):
n += 1
y_mat.append(data.iloc[p, q])
if n == data.shape[0] * data.shape[1]:
break
elif n % y_level != 0:
y_mat.extend([0] * (len(data) - 1))
elif n % y_level == 0:
y_mat.extend([0] * len(data))
y_mat = np.array(y_mat).reshape(-1, len(data))
y_mat = pd.DataFrame(y_mat) # bar图中的y变量矩阵,每一行是一个y变量
# 通过x,y_mat中的每一行y,依次绘制每一块堆积图中的每一块图
from matplotlib import cm
cm_subsection = [level for level in range(y_level)]
colors = [cm.Pastel1(color) for color in cm_subsection]
bottom = [0] * y_mat.shape[1]
createVar = locals()
for row in range(len(y_mat)):
createVar['a' + str(row)] = y_mat.iloc[row, :]
color = colors[row % y_level]
if row % y_level == 0:
bottom = bottom = [0] * y_mat.shape[1]
if math.floor(row / y_level) == 0:
label = data.columns.name + ': ' + str(data.columns[row])
plt.bar(x, createVar['a' + str(row)],
width=width[math.floor(row / y_level)], label=label, color=color)
else:
plt.bar(x, createVar['a' + str(row)],
width=width[math.floor(row / y_level)], color=color)
else:
if math.floor(row / y_level) == 0:
label = data.columns.name + ': ' + str(data.columns[row])
plt.bar(x, createVar['a' + str(row)], bottom=bottom,
width=width[math.floor(row / y_level)], label=label, color=color)
else:
plt.bar(x, createVar['a' + str(row)], bottom=bottom,
width=width[math.floor(row / y_level)], color=color)
bottom += createVar['a' + str(row)]
plt.title(j + ' vs ' + i)
group_labels = [str(name) for name in data.index]
plt.xticks(x, group_labels, rotation=rotation)
plt.ylabel(j)
plt.legend(shadow=True, loc=location)
plt.show()
读取数据
auto_ins.csv数据获取 提取码:n5ib
# os.chdir(r'.\data')
auto = pd.read_csv(r'.\data\auto_ins.csv',encoding = 'gbk')
auto.head()
EngSize | Age | Gender | Marital | exp | Owner | vAge | Garage | AntiTFD | import | Loss | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2.0 | 56 | 男 | 已婚 | 20 | 公司 | 10 | 有 | 有防盗装置 | 进口 | 0.0 |
1 | 1.8 | 41 | 男 | 已婚 | 20 | 公司 | 9 | 有 | 无防盗装置 | 国产 | 0.0 |
2 | 2.0 | 44 | 男 | 未婚 | 20 | 公司 | 8 | 有 | 有防盗装置 | 国产 | 0.0 |
3 | 1.6 | 56 | 男 | 已婚 | 20 | 公司 | 7 | 有 | 有防盗装置 | 国产 | 0.0 |
4 | 1.8 | 45 | 男 | 已婚 | 20 | 公司 | 7 | 无 | 无防盗装置 | 国产 | 0.0 |
1、map 函数
def codeMy(x):
if x>0:
return 1
else:
return 0
auto["loss_flag"]= auto.Loss.map(codeMy)
auto["loss_flag"]
0 0
1 0
2 0
3 0
4 0
..
4228 1
4229 1
4230 0
4231 1
4232 1
Name: loss_flag, Length: 4233, dtype: int64
auto["loss_flag1"]= auto.Loss.map(lambda x: 1 if x >0 else 0)
auto
EngSize | Age | Gender | Marital | exp | Owner | vAge | Garage | AntiTFD | import | Loss | loss_flag | loss_flag1 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2.0 | 56 | 男 | 已婚 | 20 | 公司 | 10 | 有 | 有防盗装置 | 进口 | 0.0 | 0 | 0 |
1 | 1.8 | 41 | 男 | 已婚 | 20 | 公司 | 9 | 有 | 无防盗装置 | 国产 | 0.0 | 0 | 0 |
2 | 2.0 | 44 | 男 | 未婚 | 20 | 公司 | 8 | 有 | 有防盗装置 | 国产 | 0.0 | 0 | 0 |
3 | 1.6 | 56 | 男 | 已婚 | 20 | 公司 | 7 | 有 | 有防盗装置 | 国产 | 0.0 | 0 | 0 |
4 | 1.8 | 45 | 男 | 已婚 | 20 | 公司 | 7 | 无 | 无防盗装置 | 国产 | 0.0 | 0 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
4228 | 1.8 | 22 | 女 | 未婚 | 0 | 私人 | 1 | 有 | 有防盗装置 | 国产 | 976.0 | 1 | 1 |
4229 | 2.5 | 22 | 男 | 未婚 | 0 | 私人 | 1 | 有 | 无防盗装置 | 进口 | 855.6 | 1 | 1 |
4230 | 1.8 | 21 | 男 | 未婚 | 0 | 私人 | 1 | 有 | 无防盗装置 | 国产 | 0.0 | 0 | 0 |
4231 | 1.8 | 21 | 女 | 未婚 | 0 | 私人 | 1 | 有 | 无防盗装置 | 进口 | 3328.0 | 1 | 1 |
4232 | 2.4 | 21 | 女 | 未婚 | 0 | 私人 | 1 | 有 | 无防盗装置 | 进口 | 1564.0 | 1 | 1 |
4233 rows × 13 columns
2、对loss_flag分布情况进行描述分析
条形图 .plot(kind=‘bar’)
auto.loss_flag.value_counts()
auto.loss_flag.value_counts().plot(kind='bar')
<matplotlib.axes._subplots.AxesSubplot at 0x271a26ed648>
3、分析是否出险和年龄、驾龄、性别、婚姻状态等变量之间的关系
添加画布
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
#是否出险和年龄
sns.boxplot(x = 'loss_flag',y = 'Age',data = auto, ax = ax1)
#是否出险和驾龄
sns.boxplot(x = 'loss_flag',y = 'exp',data = auto, ax = ax2)
<matplotlib.axes._subplots.AxesSubplot at 0x271a5e12248>
盒状图
-箱形图(Box-plot)又称为盒须图、盒式图或箱线图,是一种用作显示一组数据分散情况资料的统计图。它能显示出一组数据的最大值、最小值、中位数及上下四分位数。因形状如箱子而得名。在各种领域也经常被使用,常见于品质管理。图解如下:
seaborn.boxplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient=None, color=None, palette=None, saturation=0.75, width=0.8, dodge=True, fliersize=5, linewidth=None, whis=1.5, notch=False, ax=None, **kwargs)
- x,y:dataframe中的列名(str)或者矢量数据
- data:dataframe或者数组
- palette:调色板,控制图像的色调
- hue(str):dataframe的列名,按照列名中的值分类形成分类的条形图
- order, hue_order (lists of strings):用于控制条形图的顺序
- orient:“v”|“h” 用于控制图像使水平还是竖直显示(这通常是从输入变量的dtype推断出来的,此参数一般当不传入x、y,只传入data的时候使用)
- fliersize:float,用于指示离群值观察的标记大小
- whis:确定离群值的上下界(IQR超过低和高四分位数的比例),此范围之外的点将被识别为异常值。IQR指的是上下四分位的差值
- width:float,控制箱型图的宽度
#是否出险和性别
from stack2dim import *
stack2dim(auto,'Gender','loss_flag')
# In[121]:
#是否出险和婚姻状态
stack2dim(auto,'Marital','loss_flag')
# In[126]:
完整代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import seaborn as sns
import os
# os.chdir(r'D:\Python_Training\script_Python\4describe\homework4')
# # 使用auto_ins作如下分析
# ### 1、首先对loss重新编码为1/0,有数值为1,命名为loss_flag
auto = pd.read_csv(r'.\data\auto_ins.csv',encoding = 'gbk')
# In[134]:
def codeMy(x):
if x>0:
return 1
else:
return 0
auto["loss_flag"]= auto.Loss.map(codeMy)
#%%
auto["loss_flag1"]= auto.Loss.map(lambda x: 1 if x >0 else 0)
# ###2、对loss_flag分布情况进行描述分析
auto.loss_flag.value_counts()
# In[117]:
auto.loss_flag.value_counts()/auto.Loss.count()
# In[118]:
auto.loss_flag.value_counts().plot(kind='bar')
# ### 3、分析是否出险和年龄、驾龄、性别、婚姻状态等变量之间的关系
# In[119]:
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
#是否出险和年龄
sns.boxplot(x = 'loss_flag',y = 'Age',data = auto, ax = ax1)
#是否出险和驾龄
sns.boxplot(x = 'loss_flag',y = 'exp',data = auto, ax = ax2)
# In[120]:
#是否出险和性别
from stack2dim import *
plt.figure()
stack2dim(auto,'Gender','loss_flag')
# In[121]:
#是否出险和婚姻状态
stack2dim(auto,'Marital','loss_flag')
# In[126]: