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

如何用Matplotlib imshow绘制x范围逐行变化的棋盘格图?

用imshow绘制每行X范围不同的棋盘格图?

当然可以实现,但直接在循环里修改imshow的extent参数确实行不通——因为imshow的extent是作用于整个图像的全局参数,不是用来单独控制每一行的。你最后一次设置的extent会覆盖之前所有的配置,所以所有行都会被偏移到最后那个extent对应的位置。

那该怎么解决呢?这里有两种靠谱的方法:


方法1:用pcolormesh(推荐)

pcolormesh天生支持非均匀的坐标网格,它可以接受每行不同的X坐标,完美适配你的场景。下面是一个完整的示例:

首先模拟你的数据结构(你可以替换成自己的真实数据):

import matplotlib.pyplot as plt
import numpy as np

# 模拟你的Y值和对应的X范围
y_values = [0, 1, 2]
# 每个Y对应的40个X值(这里用linspace模拟,你可以换成自己的真实数据)
x_arrays = [
    np.linspace(20, 55, 40),  # Y=0的X值
    np.linspace(24, 49, 40),  # Y=1的X值
    np.linspace(23, 59, 40)   # Y=2的X值
]
# 模拟每个(X,Y)对应的数值(这里用随机数,你替换成自己的数据)
data = np.random.rand(len(y_values), 40)

然后用pcolormesh绘制每行的棋盘格:

fig, ax = plt.subplots(figsize=(10, 6))

for y_idx, y in enumerate(y_values):
    x = x_arrays[y_idx]
    # 计算X方向的单元格边缘(每个X点是单元格的中心,边缘取相邻中心的中点)
    x_edges = np.concatenate([
        [x[0] - (x[1]-x[0])/2],  # 第一个单元格的左边缘
        (x[1:] + x[:-1])/2,       # 中间单元格的边缘
        [x[-1] + (x[-1]-x[-2])/2] # 最后一个单元格的右边缘
    ])
    # Y方向的边缘:当前Y行的上下边界(比如Y=0对应-0.5到0.5)
    y_edges = [y - 0.5, y + 0.5]
    # 生成网格坐标
    X_grid, Y_grid = np.meshgrid(x_edges, y_edges)
    # 将当前行的数据转为2D格式(pcolormesh需要二维输入)
    row_data = data[y_idx][np.newaxis, :]
    # 绘制这一行的棋盘格,加上白色边框区分单元格
    ax.pcolormesh(X_grid, Y_grid, row_data, edgecolor='white', linewidth=0.5, cmap='viridis')

# 设置坐标轴范围和标签
ax.set_ylim(-0.5, max(y_values)+0.5)
ax.set_xlabel('X Coordinate')
ax.set_ylabel('Y Coordinate')
ax.set_title('Non-uniform X Rows Grid')
plt.colorbar(ax.collections[0], ax=ax, label='Value')
plt.show()

方法2:手动绘制矩形(更灵活)

如果你的X间隔完全没有规律(甚至不是均匀间隔),可以用matplotlib.patches.Rectangle逐个绘制每个单元格,这种方式自由度最高:

fig, ax = plt.subplots(figsize=(10, 6))
cmap = plt.cm.viridis

for y_idx, y in enumerate(y_values):
    x = x_arrays[y_idx]
    row_vals = data[y_idx]
    # 计算每个单元格的宽度和左边界
    if len(x) > 1:
        widths = np.diff(x)
        # 第一个单元格的左边界 = 第一个X值 - 第一个宽度的一半
        lefts = np.concatenate([[x[0] - widths[0]/2], x[:-1] + widths/2])
    else:
        # 处理只有一个X值的特殊情况
        widths = [1]
        lefts = [x[0] - 0.5]
    # Y方向的底部坐标和单元格高度
    y_bottom = y - 0.5
    cell_height = 1

    # 逐个绘制单元格
    for left, width, val in zip(lefts, widths, row_vals):
        # 根据数值获取颜色
        color = cmap(val / data.max())
        # 创建矩形并添加到坐标轴
        rect = plt.Rectangle((left, y_bottom), width, cell_height, facecolor=color, edgecolor='white')
        ax.add_patch(rect)

# 设置坐标轴范围
min_x = min([min(x) - (x[1]-x[0])/2 for x in x_arrays])
max_x = max([max(x) + (x[-1]-x[-2])/2 for x in x_arrays])
ax.set_xlim(min_x, max_x)
ax.set_ylim(-0.5, max(y_values)+0.5)

# 添加颜色条和标签
sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=data.min(), vmax=data.max()))
sm.set_array([])
plt.colorbar(sm, ax=ax, label='Value')
ax.set_xlabel('X Coordinate')
ax.set_ylabel('Y Coordinate')
ax.set_title('Manual Rectangle Grid for Non-uniform X')
plt.show()

为什么imshow不行?

再补充解释一下:imshow是为规则网格数据设计的,它默认假设每行的X范围是完全一致的,只是通过extent把整个数据块映射到坐标轴上。它没有单独控制每行X范围的能力,所以你循环修改extent只会不断覆盖全局设置,导致所有行都对齐到最后一次的extent。

所以针对你的非均匀X行场景,pcolormesh或者手动绘制矩形才是正确的选择~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:13:39