|||
refer to: https://cloud.tencent.com/developer/article/1790529
在推出散点颜色密度图的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 pdimport numpy as npimport matplotlibimport matplotlib.cm as cmimport 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()#预测值2y3 = test_data['DNN_model01_estimated'].values.ravel()#预测值3nbins = 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 npimport 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')plt.show()
如果没有以下操作:
idx = z.argsort()x, y, z = x[idx], y[idx], z[idx]
所绘制的结果如下:
可以看出红圈中还是和排序前的有较大不同的。
原创不易,整理代码和数据更是不易,希望大家多一份理解和支持啊!
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-27 17:59
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社