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

Matplotlib中add_axes子图与主图Y坐标不匹配问题求解

问题

需求:创建主图,并在主图坐标系的指定位置添加多个子图,要求子图Y坐标与主图匹配,子图X坐标为本地坐标。
问题:现有代码运行后,子图Y坐标与主图不匹配,例如中间子图应覆盖主图Y=0到20区域,却超出该范围。
尝试:已尝试去除内边距、使用tight_layout(),均未解决问题。

附原代码:

import matplotlib.pyplot as plt
# Master plot dimensions
master_xlims = (0, 2500)
master_ylims = (-40, 40)

# Create a master figure
fig = plt.figure(figsize=(10, 5),dpi = 300)

# fig.tight_layout()
# Master Axes - Setting limits to master plot dimensions
ax_master = fig.add_subplot(111)
ax_master.set_xlim(master_xlims)
ax_master.set_ylim(master_ylims)
ax_master.plot([0, 2500], [0, 0], color='blue')  # Example line
ax_master.fill_between([0, 2500], [-25, -25], [0, 0], color='gray', alpha=0.5)  # Example shaded area

master_trans = ax_master.transAxes.inverted()
x,y = master_trans.transform((2500,-40))
print(x,y)
# Subplot information: (x, y, width, height) in master coordinates
subplots_info = [
    (100, 0, 300, 10),
    (1500, -20, 300, 15),
    (500, 0, 300, 20)
]

# Create each subplot within the master plot
for x, y, width, height in subplots_info:
    # Normalize x position and width relative to the master plot's width
    # x,y = master_trans.transform(ax_master.transData.transform((x,y)))
    
    norm_x = x / master_xlims[1]
    norm_width = width / master_xlims[1]

    # Normalize y position and height relative to the figure's dimensions
    # Calculate the bottom position in normalized coordinates considering the figure's height
    fig_bottom = (y - master_ylims[0]) / (master_ylims[1] - master_ylims[0])
    fig_height = height / (master_ylims[1] - master_ylims[0])

    # Add subplot
    ax_sub = fig.add_axes([norm_x, fig_bottom, norm_width, fig_height])
    ax_sub.set_ylim([y, y + height])  # Matching the master plot's y-coordinates exactly
    ax_sub.plot()  # You may add actual plot commands here
    ax_sub.set_title(f"Subplot from y={y} to y={y+height}")
    ax_sub.margins(0.00)
    # pos = ax_sub.get_position()
    # ax_sub.set_position([pos.x0, fig_bottom, pos.width, fig_height])
    


plt.show()
解决方案

原代码的核心问题是直接用主图Y坐标的比例计算子图在画布中的位置,但主图坐标轴默认不会占满整个画布(存在边距),导致位置映射出错。正确做法是通过数据坐标转画布归一化坐标的方式,精准计算子图位置:

修改后代码

import matplotlib.pyplot as plt

# 主图坐标范围
master_xlims = (0, 2500)
master_ylims = (-40, 40)

# 创建主画布
fig = plt.figure(figsize=(10, 5), dpi=300)

# 创建主坐标轴并设置范围
ax_master = fig.add_subplot(111)
ax_master.set_xlim(master_xlims)
ax_master.set_ylim(master_ylims)
ax_master.plot([0, 2500], [0, 0], color='blue')
ax_master.fill_between([0, 2500], [-25, -25], [0, 0], color='gray', alpha=0.5)

# 子图信息:(主图X起始, 主图Y起始, 主图X宽度, 主图Y高度)
subplots_info = [
    (100, 0, 300, 10),
    (1500, -20, 300, 15),
    (500, 0, 300, 20)
]

for x_start, y_start, x_width, y_height in subplots_info:
    # 将子图的四个角从主图数据坐标转换为画布归一化坐标
    # 左下角(x_start, y_start)
    bottom_left = ax_master.transData.transform((x_start, y_start))
    bottom_left_norm = fig.transFigure.inverted().transform(bottom_left)
    # 右上角(x_start+x_width, y_start+y_height)
    top_right = ax_master.transData.transform((x_start + x_width, y_start + y_height))
    top_right_norm = fig.transFigure.inverted().transform(top_right)
    
    # 计算子图在画布中的位置和尺寸(归一化坐标)
    norm_x = bottom_left_norm[0]
    norm_y = bottom_left_norm[1]
    norm_width = top_right_norm[0] - bottom_left_norm[0]
    norm_height = top_right_norm[1] - bottom_left_norm[1]
    
    # 添加子图
    ax_sub = fig.add_axes([norm_x, norm_y, norm_width, norm_height])
    ax_sub.set_ylim([y_start, y_start + y_height])
    ax_sub.set_xlim([0, x_width])  # 子图X用本地坐标(0到自身宽度)
    ax_sub.plot([0, x_width], [y_start, y_start + y_height], color='red')  # 示例线
    ax_sub.set_title(f"Y: {y_start} to {y_start+y_height}")
    ax_sub.margins(0)

plt.show()

关键说明

  1. 坐标转换逻辑:
    • ax_master.transData.transform():将主图的数据坐标转换为画布的像素坐标
    • fig.transFigure.inverted().transform():将像素坐标转换为画布的归一化坐标(0-1范围),确保子图位置完全对应主图的数据区域,不受画布边距影响
  2. 子图本地X坐标:设置子图X轴范围为[0, x_width],实现需求中的本地坐标效果
  3. 去除冗余操作:删掉原代码中无效的坐标转换尝试,简化逻辑,避免干扰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:34:54