You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:45:50