如何在Matplotlib表格单元格内绘制迷你条形图
解决Matplotlib表格单元格内迷你条形图渲染问题
问题分析
你的代码主要存在三个核心问题:
- 单元格坐标计算错误:Matplotlib表格采用归一化坐标系,
cell.get_y()返回的是单元格顶部位置,而矩形绘制需要以单元格底部作为y轴起始点 - Patch层级被遮挡:默认表格的zorder高于手动添加的矩形,导致条形图被单元格背景覆盖
- 缺少红色区域内的白色占比文本实现
修正后的完整代码
import matplotlib.pyplot as plt import pandas as pd import numpy as np # 创建示例数据 df = pd.DataFrame({ 'A': np.random.randint(1, 10, 10), 'B': np.random.randint(1, 10, 10), 'C': np.random.randint(1, 10, 10), 'D': np.random.randint(1, 10, 10), 'BAR': np.random.randint(1, 10, 10), }) # 绘制迷你条形图(含白色占比文本) def draw_mini_bar(ax, cell, percentage): # 获取单元格的归一化坐标与尺寸 x_left = cell.get_x() y_bottom = cell.get_y() - cell.get_height() cell_width = cell.get_width() cell_height = cell.get_height() # 绘制绿色底色(填充整个单元格) green_rect = plt.Rectangle( (x_left, y_bottom), cell_width, cell_height, facecolor='#76ed33', zorder=10 # 高于表格层级,避免被遮挡 ) ax.add_patch(green_rect) # 绘制红色分段(按百分比占宽) red_width = cell_width * percentage / 100 red_rect = plt.Rectangle( (x_left, y_bottom), red_width, cell_height, facecolor='#f55d2f', zorder=11 ) ax.add_patch(red_rect) # 在红色区域中心绘制白色占比文本 text_x = x_left + red_width / 2 text_y = y_bottom + cell_height / 2 ax.text( text_x, text_y, f"{percentage}%", ha='center', va='center', color='white', fontsize=12, zorder=12 ) # 渲染表格函数 def render_mpl_table(data, col_width=3.0, row_height=0.625, font_size=14, header_color='#40466e', row_colors=['#f1f1f2', '#ffffff'], edge_color='w', bbox=[0, 0, 1, 1], ax=None, **kwargs): if ax is None: size = (np.array(data.shape[::-1]) + np.array([0, 1])) * np.array([col_width, row_height]) fig, ax = plt.subplots(figsize=size) ax.axis('off') # 创建表格并设置层级低于条形图 mpl_table = ax.table(cellText=data.values, bbox=bbox, colLabels=data.columns, zorder=5, **kwargs) # 统一表格字体大小 mpl_table.auto_set_font_size(False) mpl_table.set_fontsize(font_size) for k, cell in mpl_table._cells.items(): cell.set_edgecolor(edge_color) if k[0] == 0: cell.set_text_props(weight='bold', color='w') cell.set_facecolor(header_color) else: cell.set_facecolor(row_colors[k[0]%len(row_colors)]) # 为最后一列的单元格绘制迷你条形图 if k[0] > 0 and k[1] == len(data.columns) - 1: # 暂用50%占比,后续可替换为实际数据计算值 draw_mini_bar(ax, cell, 50) plt.show() # 调用渲染函数 render_mpl_table(df)
关键修改说明
- 坐标校正:通过
cell.get_y() - cell.get_height()获取单元格底部y坐标,确保矩形完全填充单元格区域 - 层级控制:设置表格zorder为5,条形图和文本的zorder依次提高,保证条形图显示在单元格背景上方
- 文本实现:在红色矩形中心添加白色百分比文本,通过
ha='center'和va='center'实现精准居中 - 样式优化:添加字体大小统一设置,避免表格自动调整字体导致的样式混乱
后续如需动态调整占比,只需将draw_mini_bar的percentage参数替换为实际数据的计算值(例如data.iloc[k[0]-1, k[1]] * 10等逻辑)即可。
内容的提问来源于stack exchange,提问作者Guillem Servera
相关产品推荐
相关产品推荐

