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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:36:13