最近实习数据分析需要画两个图共享x轴,
我之前找到了matplotlib如何实现:http://www.developerq.com/article/1516290674
但是不知道如何移植到seaborn上,经过N次实验终于找到方法了!
需求:折线图和柱状图共享x轴,y轴双坐标,一侧是折线图的坐标,一侧是柱状图的坐标。柱状图每个柱上有标注,折线图每个点上有标注。
fig = plt.figure(figsize=[18,6])#设定图片大小
ax1 = fig.add_subplot(111)#添加第一副图
ax2 = ax1.twinx()#共享x轴,这句很关键!
"""
画WOE值随hit_data变化的柱状图
"""
sns.barplot(x='hit_data', y='sum_people', data=result.reset_index(),ax=ax1,alpha=0.8)#画柱状图,注意ax是选择画布
rects = ax1.patches
labels=result['labels']#一个series
for rect, label in zip(rects, labels):#柱状图标记
height = rect.get_height()
ax1.text(rect.get_x() +division(rect.get_width() , 2), height + 3, label, ha='center', va='bottom')#为每个柱写标注
ax1.axes.set_ylabel(u"进件数", fontsize=15)
ax1.axes.set_xlabel(u"{0} (单位:{1})".format(xName,xDanwei), fontsize=15) # 设置x 坐标label
"""
画WOE值随hit_data变化的折线图
"""
sns.pointplot(result.index, result['woe'], ax=ax2)#画在ax2画布上
for c in ax2.collections: # 这三行为折线图的点加注释
for of in c.get_offsets():
if(of[1]<0):
dotlabel=1/math.e**of[1]
else:
dotlabel=math.e**of[1]
ax2.annotate(round(dotlabel,2), of)
ax2.plot([-1, x.max()+1],[0,0],color='r')#画一条iv值(在ax2中)=0的红线
ax2.axes.set_ylabel(u"好 woe值 坏", fontsize=15) # 设置y坐标label
ax2.axes.set_title(u"折线图", fontsize=15)
#plt.show()
fig.savefig(u"rulesetid{0}ruleid{1}woe值随{2}变化趋势图".format(str(rulesetid),str(ruleid),xName)) #保存图片
plt.close(fig)#把图片释放掉,否则循环批量跑的时候保存图片会产生重叠
关键:
1.画图的时候加ax参数选择画布
2.共享x轴时的画图可以理解为像PS的图层!ax=ax1是一层画布,ax=ax2是第二层画布,因为先画的ax1后画的ax2,所以ax2覆盖在ax1上面,这意味着折线图覆盖在柱状图上,当折线图点的标注有柱状图柱的标注重合时,显示折线图点的标注,在上层的图的坐标轴在右侧。同理,无论用seaborn画什么图,加ax参数都可以选择画布。
3.ax2 = ax1.twinx()#共享x轴,这句很关键!