01. 引言
在推出散点颜色密度图的matplotlib 绘制教程后,有小伙伴反应能否出一篇多子图共用一个colorbar的系列教程,这里也就使用自己的数据进行绘制(数据一共四列,具体为真实值和使用三个模型计算的预测值)。
02. 实现颜色和数值间的对应关系
在绘制多子图共用colorbar时,最重要的就是对颜色映射进行设置,这里使用了matplotlib.color.Normalize()进行颜色和数值对应设置。先看一下使用默认设置的结果,每个子图对应一个colorbar。效果如下:
可以看出,每个子图对应的值颜色都是不同,这样不利于对比,采用matplotlib.color.Normalize()操作后就可有效解决此问题:
代码语言:javascript复制#将颜色映射到 vmin~vmax 之间
norm = matplotlib.colors.Normalize(vmin=0, vmax=60)
效果如下:
至于其他拟合线、EE等的设置,可以参考之前的文章Python-matplotlib 学术散点图 EE 统计及绘制 Python-matplotlib 学术散点图完善
03. 详细代码
多子图共用colorbar的详细代码如下:
代码语言:javascript复制import pandas as pd
import numpy as np
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['Arial']
test_data = pd.read_excel('GBRT_SVR_DNN_esti_save_angle_process.xlsx')
x = test_data['true_data'].values.ravel() #真实值
y = test_data['model01_estimated'].values.ravel()#预测值
y2 = test_data['SVR_estimated'].values.ravel()#预测值2
y3 = test_data['DNN_model01_estimated'].values.ravel()#预测值3
nbins = 150
#模型一结果
H, xedges, yedges = np.histogram2d(x, y, bins=nbins)
H = np.rot90(H)
H = np.flipud(H)
Hmasked = np.ma.masked_where(H==0,H)
#模型二结果
H2, xedges2, yedges2 = np.histogram2d(x, y2, bins=nbins)
H2 = np.rot90(H2)
H2 = np.flipud(H2)
Hmasked2 = np.ma.masked_where(H2==0,H2)
#模型三结果
H3, xedges3, yedges3 = np.histogram2d(x, y3, bins=nbins)
H3 = np.rot90(H3)
H3 = np.flipud(H3)
Hmasked3 = np.ma.masked_where(H3==0,H3)
#可视化绘制
fig, (ax1, ax2,ax3) = plt.subplots(nrows=1,ncols=3,figsize=(12,3),dpi=200)
#将颜色映射到 vmin~vmax 之间
norm = matplotlib.colors.Normalize(vmin=0, vmax=60)
#模型一结果绘图
im1 = ax1.pcolormesh(xedges, yedges, Hmasked, cmap=cm.get_cmap('jet'),norm=norm)
#fig.colorbar(im1, ax=ax1)
#模型二结果绘图
im2 = ax2.pcolormesh(xedges2, yedges2, Hmasked2, cmap=cm.get_cmap('jet'), norm=norm)
#fig.colorbar(im2, ax=ax2)
#模型二结果绘图
im3 = ax3.pcolormesh(xedges3, yedges3, Hmasked3, cmap=cm.get_cmap('jet'), norm=norm,)
#fig.colorbar(im3, ax=ax3)
#前面三个子图的总宽度 为 全部宽度的 0.9;剩下的0.1用来放置colorbar
fig.subplots_adjust(right=0.9)
position = fig.add_axes([0.92, 0.12, 0.015, .78 ])#位置[左,下,右,上]
cb = fig.colorbar(im3, cax=position)
#设置colorbar标签字体等
colorbarfontdict = {"size":15,"color":"k",'family':'Times New Roman'}
cb.ax.set_title('Counts',fontdict=colorbarfontdict,pad=8)
cb.ax.tick_params(labelsize=11,direction='in')
cb.ax.set_yticklabels(['0','10','20','30','40','50','>60'],family='Times New Roman')
#suptitle()中x,y 属性的设置为调整title与子图(subplots)之间的距离
fig.suptitle('One Colorbar for Multiple Plot ',size=20,family='Times New Roman',x=.5,y=1.05)
plt.savefig(r'E:Data_resoursesDataCharm 公众号Python学术图表绘制scatter_One_Colorbar.png',
width=7,height=5,dpi=900,bbox_inches='tight')
plt.show()
这里:
代码语言:javascript复制#设置colorbar标签字体等
colorbarfontdict = {"size":15,"color":"k",'family':'Times New Roman'}
cb.ax.set_title('Counts',fontdict=colorbarfontdict,pad=8)
cb.ax.tick_params(labelsize=11,direction='in')
cb.ax.set_yticklabels(['0','10','20','30','40','50','>60'],family='Times New Roman')
实现了对colorbar的定制化需求。
此外,我们设置colorbar也不是只绘制最后一个子图的colorbar,而其他子图不绘制,那样容易导致子图大小不一。这里单独绘制了colorbar,代码如下:
代码语言:javascript复制fig.subplots_adjust(right=0.9)
position = fig.add_axes([0.92, 0.12, 0.015, .78 ])#位置[左,下,右,上]
cb = fig.colorbar(im3, cax=position)
这也是多子图共用一个colorbar避免大小不一的一个小技巧,希望大家可以记住。
04. 高斯核密度估计颜色映射
还有小伙伴想绘制如下的颜色密度散点图:
可以看出颜色密集部分出现“光滑”处理,其实就是通过核密度估计函数将 真实值和预测值之间进行密度值估计,再进行一个排序即可,详细代码如下:
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
x = test_data['true_data'].values.ravel() #真实值
y = test_data['model01_estimated'].values.ravel()#预测值
#计算点密度
#np.vstack:按垂直方向(行顺序)堆叠数组构成一个新的数组
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
fig, ax = plt.subplots(figsize=(7,5),dpi=200)
ax.scatter(x, y, c=z, s=3, edgecolor='')
plt.savefig(r'E:Data_resoursesDataCharm 公众号Python学术图表绘制scatter_gaussian_kde.png',
width=7,height=5,dpi=900,bbox_inches='tight')
plt.show()
如果没有以下操作:
代码语言:javascript复制idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
所绘制的结果如下:
可以看出红圈中还是和排序前的有较大不同的。
05. 总结
原创不易,整理代码和数据更是不易,希望大家多一份理解和支持啊!
为了大家更好的学习交流,DataCharm的学习交流群已经建立,由于群的二维码连接易失效,可以通过扫面下方二维码,添加本人微信,做自我介绍啊,要不然我都不知道是谁