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

使用matplotlib.patches.Rectangle绘制矩形出现内外线宽不一致问题求助

问题描述

我用matplotlib的matplotlib.patches.Rectangle把矩阵的列绘制成独立矩形,但所有“内部”线条的宽度看起来比“外部”线条更粗,这是怎么回事?这是否和相关GitHub issue有关?

以下是最小可复现示例:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.patches as patches

# 设置随机种子
np.random.seed(42)

# 定义行列数
num_rows = 5
num_cols = 5

# 定义矩阵列之间的间隙大小
column_gap = 0.3

# 定义线条宽度
linewidth = 5

# 定义每个方形单元格的边长
cell_size = 1  

# 初始化矩阵
matrix = np.random.rand(num_rows, num_cols)

# 创建画布和轴
fig, ax = plt.subplots(figsize=(8,6))

# 创建seaborn颜色调色板并反转
palette = sns.color_palette("RdYlBu", as_cmap=True).reversed()

# 逐个绘制带列间隙的单元格
for i in range(num_rows):
    for j in range(num_cols):
        
        # 计算单元格颜色
        color = palette(matrix[i, j])
        
        edgecolor = 'black' if column_gap > 0 else None
        
        # 添加仅在x方向带间隙的矩形补丁
        rect = patches.Rectangle(
            (j * (cell_size + column_gap), i * cell_size),  # 列间隙应用到x位置
            cell_size,                                      # 单元格宽度
            cell_size,                                      # 单元格高度
            facecolor=color,
            edgecolor=edgecolor,
            linewidth=linewidth
        )
        
        ax.add_patch(rect)

if column_gap > 0:
    # 隐藏默认边框
    ax.spines[:].set_visible(False)

# 设置轴范围以容纳所有单元格
ax.set_xlim(0, num_cols * (cell_size + column_gap) - column_gap)
ax.set_ylim(0, num_rows * cell_size)

# 禁用刻度
ax.set_xticks([])
ax.set_yticks([])

fig.show()

运行效果如下:
线条宽度不一致的矩形效果


原因与解决方案

原因分析

你看到的“内部线条更粗”是相邻矩形边框重叠绘制导致的:

  • 同一行中,相邻矩形的右侧边框与左侧边框在x方向紧挨着(无间隙),黑色边框叠加后,视觉宽度变成了linewidth*2。
  • 最左/最右侧的矩形只有单侧边框,显示的是原始linewidth宽度,因此看起来比内部线条细。

这个现象和你提到的GitHub issue无关,那个问题是关于缩放级别对线条宽度的影响,而这里是纯粹的边框叠加问题。

解决方案

避免边框重叠的核心是让每个矩形只绘制必要的边框,而非四条边全画:

  • 第一列矩形:保留四条边
  • 中间列矩形:只保留上、下、右边框(左边框与前一个矩形的右边框重叠,无需重复绘制)
  • 最后一列矩形:保留上、下、左边框(右侧无相邻矩形,不会重叠)

修改后的核心代码如下:

# 逐个绘制带列间隙的单元格
for i in range(num_rows):
    for j in range(num_cols):
        
        # 计算单元格颜色
        color = palette(matrix[i, j])
        
        if column_gap > 0:
            edgecolor = 'black'
            # 根据列位置设置分边线条宽度
            if j == 0:
                # 第一列:绘制四条边
                side_linewidths = [linewidth, linewidth, linewidth, linewidth]  # 左、右、上、下
            elif j == num_cols - 1:
                # 最后一列:不画右侧边框
                side_linewidths = [linewidth, 0, linewidth, linewidth]
            else:
                # 中间列:不画左侧边框
                side_linewidths = [0, linewidth, linewidth, linewidth]
        else:
            edgecolor = None
            side_linewidths = None
        
        # 添加矩形补丁
        rect = patches.Rectangle(
            (j * (cell_size + column_gap), i * cell_size),
            cell_size,
            cell_size,
            facecolor=color,
            edgecolor=edgecolor,
            linewidth=side_linewidths  # 使用分边宽度
        )
        
        ax.add_patch(rect)

更简洁的替代方案

如果不想逐个列判断,也可以统一把所有矩形的左侧边框设为0,仅保留第一列的左侧边框:

for i in range(num_rows):
    for j in range(num_cols):
        color = palette(matrix[i, j])
        edgecolor = 'black' if column_gap > 0 else None
        # 仅第一列保留左侧边框,其余列左侧边框宽度为0
        left_lw = linewidth if j == 0 else 0
        rect = patches.Rectangle(
            (j * (cell_size + column_gap), i * cell_size),
            cell_size,
            cell_size,
            facecolor=color,
            edgecolor=edgecolor,
            linewidth=[left_lw, linewidth, linewidth, linewidth]
        )
        ax.add_patch(rect)

修改后,所有内部线条与外部线条的视觉宽度会完全一致。

内容的提问来源于stack exchange,提问作者Johannes Wiesner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 09:05:07