Matplotlib为分面图添加黑边框及带星号标注文本的方法
Matplotlib分面图定制实现方案
核心实现逻辑
- 全分面黑色外边框:在Figure画布层添加矩形补丁实现,边框独立于单个子图,完整包裹所有子图区域,不会和子图自身边框冲突
- 带星号的标注文本:支持两种常用添加方式,一是全局画布层面的统一显著性说明标注,二是单个子图内的柱间对比星号标注,可按需调整位置、字号、星号数量
完整可运行修改代码如下:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Rectangle pd.set_option('max_columns', None) # 原有数据集 data = { 'type_sale': ['g_1','g_2','g_3','g_4','g_5','g_6','g_7','g_8','g_9','g_10'], 'open':[70,20,24,80,20,20,60,20,20,20], 'closed':[30,14,20,10,10,40,10,10,10,10], } df = pd.DataFrame(data, columns = ['type_sale','open','closed']) fig, axs = plt.subplots(2,2, figsize=(8,6)) # 调整子图边距,给外边框和标注预留空间 plt.subplots_adjust(wspace=0.2, hspace=0.6, top=0.9, left=0.08, right=0.92, bottom=0.08) # 绘制原有堆叠柱状图 df.plot(x='type_sale', kind='bar', stacked=True, title='Stacked Bar Graph by dataframe',ax=axs[0,0], legend=None) df.plot(x='type_sale', kind='bar', stacked=True, title='Stacked Bar Graph by dataframe', ax=axs[0,1], legend=None) df.plot(x='type_sale', kind='bar', stacked=True, title='Stacked Bar Graph by dataframe',ax=axs[1,0], legend=None) df.plot(x='type_sale', kind='bar', stacked=True,title='Stacked Bar Graph by dataframe', ax=axs[1,1], legend=None) # 1. 添加整个分面区域的黑色外边框 fig.patches.append(Rectangle((0.05, 0.05), 0.9, 0.87, transform=fig.transFigure, fill=False, color='black', linewidth=1.5)) # 2. 添加带星号的标注,以下是两种常用场景示例 # 场景1:全局统一标注(比如显著性说明) fig.text(0.82, 0.93, '* p<0.05\n** p<0.01\n*** p<0.001', fontsize=10) # 场景2:单个子图内的柱间显著性标注(以第一个子图g1和g4的对比为例) # 绘制标注横线 axs[0,0].plot([0, 3], [105, 105], color='black', linewidth=1) # 添加居中星号 axs[0,0].text(1.5, 106, '**', ha='center', fontsize=12) plt.suptitle(t='Stacked Bar Graph by dataframe', fontsize=16, y=0.96) plt.show()
参数调整说明:
- 外边框部分:
Rectangle((0.05, 0.05), 0.9, 0.87)前两个值是边框左下角的标准化figure坐标(取值范围0-1,(0,0)对应画布左下角),后两个值是边框的宽度和高度,可根据自己的子图边距微调数值,保证刚好包裹所有子图即可;linewidth控制边框粗细,color可修改边框颜色- 星号标注部分:全局标注用
fig.text(),前两个参数是标准化画布坐标,直接输入要显示的星号和对应说明文本即可;子图内的柱间标注,横线的x坐标对应柱子的索引位置(第一个柱子索引为0),y坐标要高于柱子最高值,再用ax.text()把星号放在横线中间,设置ha='center'即可保证星号居中;如果不需要对比横线,直接调用ax.text()在指定位置放置星号即可
内容的提问来源于stack exchange,提问作者silent_hunter
相关产品推荐
相关产品推荐

