在推出散点颜色密度图的matplotlib 绘制教程后,有小伙伴反应能否出一篇 多子图共用一个colorbar 的系列教程,这里也就使用自己的数据进行绘制(数据一共四列,具体为 真实值 和使用 三个模型 计算的 预测值 )。
在绘制多子图共用colorbar时,最重要的就是对颜色映射进行设置,这里使用了matplotlib.color.Normalize()进行颜色和数值对应设置。先看一下使用默认设置的结果,每个子图对应一个colorbar。效果如下:
可以看出,每个子图对应的值颜色都是不同,这样不利于对比,采用matplotlib.color.Normalize()操作后就可有效解决此问题:
#将颜色映射到 vmin~vmax 之间 norm = matplotlib.colors.Normalize(vmin=0, vmax=60)
效果如下:
至于其他拟合线、EE等的设置,可以参考之前的文章 Python-matplotlib 学术散点图 EE 统计及绘制 Python-matplotlib 学术散点图完善
多子图共用colorbar的详细代码如下:
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_resourses\DataCharm 公众号\Python\学术图表绘制\scatter_One_Colorbar.png', width=7,height=5,dpi=900,bbox_inches='tight') plt.show()
这里:
#设置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, 代码如下 :
fig.subplots_adjust(right=0.9) position = fig.add_axes([0.92, 0.12, 0.015, .78 ])#位置[左,下,右,上] cb = fig.colorbar(im3, cax=position)
这也是多子图共用一个colorbar 避免大小不一 的一个小技巧,希望大家可以记住。
还有小伙伴想绘制如下的颜色密度散点图:
可以看出颜色密集部分出现“光滑”处理,其实就是通过核密度估计函数将 真实值和预测值之间进行密度值估计,再进行一个排序即可,详细代码如下:
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_resourses\DataCharm 公众号\Python\学术图表绘制\scatter_gaussian_kde.png', width=7,height=5,dpi=900,bbox_inches='tight')