如何在Matplotlib图表底部添加不同尺寸的方形图例?
问题描述
我通过以下代码生成了对应的图表:
import matplotlib import matplotlib.pyplot as plt from matplotlib import colors import matplotlib.gridspec as gridspec import matplotlib.ticker as plticker cmap = matplotlib.colors.LinearSegmentedColormap.from_list('', ['#41fdfe', '#fffe7a', '#021bf9', '#363737', '#840000' , '#ad8150' , '#e6daa6' , '#89fe05']) fig = plt.figure(figsize=(8, 6)) gs = gridspec.GridSpec(1, 2, width_ratios=[7, 1] , hspace = 6.0 , wspace = 0.0) ax0 = plt.subplot(gs[0]) ax0.imshow(data_first, interpolation='none', origin='lower', cmap=cmap) color = ['brown', 'grey', '#d1b26f' , 'brown' , '#ad8150', 'grey' , 'blue'] for y in range(5): for x in range(3): if difference[y , x] >= 0.6: size = 1200 elif difference[y , x] >= 0.4: size = 1000 elif difference[y,x] >= 0.1: size = 600 elif difference[y , x] <= 0.1: size = 300 ax0.scatter(x, y, s=size , c = color[int(data_second[y,x])], marker='s' , edgecolor = 'k') loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals ax0.xaxis.set_major_locator(loc) ax0.yaxis.set_major_locator(loc) cb_colors = ["#41fdfe", "blue", "brown" , '#d1b26f','#ad8150' , "grey"] num_colors = len(cb_colors) cmap_ = matplotlib.colors.ListedColormap(cb_colors) cax = fig.add_axes([0.7, 0.3, 0.1, 0.5]) cb = matplotlib.colorbar.ColorbarBase(cax, orientation='vertical', cmap=cmap_, norm=plt.Normalize( - 0.5 , num_colors - 0.5 )) cb.set_ticks(range(num_colors)) cb.ax.set_yticklabels(["Cumulative rainfall", "Distribution of \n the rainfall event", "SM: layer 3 ","SM : layer 2 " , "SM : layer 1" , "Snow melt"])
请问如何在图表底部(如红框所示位置)添加不同尺寸的方形图例?非常感谢。
解决方案
可以通过创建自定义图例元素的方式,在图表底部添加对应尺寸的方形图例,具体实现如下:
步骤1:定义尺寸与标签的对应关系
先把代码中用到的尺寸阈值和对应标签整理成列表:
size_labels = [r'$\geq 0.6$', r'$\geq 0.4$', r'$\geq 0.1$', r'$\leq 0.1$'] size_values = [1200, 1000, 600, 300]
步骤2:创建自定义图例标记
使用matplotlib.lines.Line2D生成和图中一致的方形标记,注意转换尺寸单位(scatter的s是面积,Line2D的markersize是边长):
import matplotlib.lines as mlines legend_elements = [mlines.Line2D([], [], marker='s', color='white', markerfacecolor='grey', markeredgecolor='k', markersize=pow(s, 0.5)/2, # 转换面积为视觉一致的边长 label=lab) for s, lab in zip(size_values, size_labels)]
步骤3:添加底部图例并调整布局
调整图表底部边距避免图例被截断,然后在底部居中位置添加图例:
# 增加底部边距,预留图例空间 plt.subplots_adjust(bottom=0.2) # 在底部居中添加图例,ncol设置为4让图例横向排列 plt.legend(handles=legend_elements, loc='lower center', bbox_to_anchor=(0.35, -0.15), # 根据实际布局微调位置 ncol=4, frameon=False)
完整修改后代码
import matplotlib import matplotlib.pyplot as plt from matplotlib import colors import matplotlib.gridspec as gridspec import matplotlib.ticker as plticker import matplotlib.lines as mlines # 示例数据(替换为你的真实数据) import numpy as np data_first = np.random.rand(5,3) difference = np.random.rand(5,3) data_second = np.random.randint(0,7,(5,3)) cmap = matplotlib.colors.LinearSegmentedColormap.from_list('', ['#41fdfe', '#fffe7a', '#021bf9', '#363737', '#840000' , '#ad8150' , '#e6daa6' , '#89fe05']) fig = plt.figure(figsize=(8, 6)) gs = gridspec.GridSpec(1, 2, width_ratios=[7, 1] , hspace = 6.0 , wspace = 0.0) ax0 = plt.subplot(gs[0]) ax0.imshow(data_first, interpolation='none', origin='lower', cmap=cmap) color = ['brown', 'grey', '#d1b26f' , 'brown' , '#ad8150', 'grey' , 'blue'] for y in range(5): for x in range(3): if difference[y , x] >= 0.6: size = 1200 elif difference[y , x] >= 0.4: size = 1000 elif difference[y,x] >= 0.1: size = 600 elif difference[y , x] <= 0.1: size = 300 ax0.scatter(x, y, s=size , c = color[int(data_second[y,x])], marker='s' , edgecolor = 'k') loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals ax0.xaxis.set_major_locator(loc) ax0.yaxis.set_major_locator(loc) cb_colors = ["#41fdfe", "blue", "brown" , '#d1b26f','#ad8150' , "grey"] num_colors = len(cb_colors) cmap_ = matplotlib.colors.ListedColormap(cb_colors) cax = fig.add_axes([0.7, 0.3, 0.1, 0.5]) cb = matplotlib.colorbar.ColorbarBase(cax, orientation='vertical', cmap=cmap_, norm=plt.Normalize( - 0.5 , num_colors - 0.5 )) cb.set_ticks(range(num_colors)) cb.ax.set_yticklabels(["Cumulative rainfall", "Distribution of \n the rainfall event", "SM: layer 3 ","SM : layer 2 " , "SM : layer 1" , "Snow melt"]) # --- 添加尺寸图例的代码 --- size_labels = [r'$\geq 0.6$', r'$\geq 0.4$', r'$\geq 0.1$', r'$\leq 0.1$'] size_values = [1200, 1000, 600, 300] legend_elements = [mlines.Line2D([], [], marker='s', color='white', markerfacecolor='grey', markeredgecolor='k', markersize=pow(s, 0.5)/2, label=lab) for s, lab in zip(size_values, size_labels)] plt.subplots_adjust(bottom=0.2) plt.legend(handles=legend_elements, loc='lower center', bbox_to_anchor=(0.35, -0.15), ncol=4, frameon=False) plt.show()
内容的提问来源于stack exchange,提问作者zorals
相关产品推荐
相关产品推荐

