Matplotlib子图:共享坐标轴且坐标轴单位相等的实现问题
实现共享Y轴、等比例坐标轴且适配X范围的双图布局
嘿,我完全懂你想要的效果——就是那种两个子图共享Y轴,既能自定义Y轴范围,又能保证X/Y轴单位相等(画圆不会变成椭圆),还能让子图尺寸自动适配你设定的X轴范围对吧?我之前也折腾过类似的需求,给你整理了一段可以直接跑的代码,顺便一步步拆解关键步骤:
完整代码示例
import matplotlib.pyplot as plt # 1. 创建共享Y轴的双列子图,初始figsize只是占位用 fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True, figsize=(8, 4)) # 2. 自定义Y轴范围(两个子图共享,只需要设置一次) y_min, y_max = -5, 5 ax1.set_ylim(y_min, y_max) # 3. 分别自定义两个子图的X轴范围 x1_range = [-3, 3] # 第一个子图的X范围 x2_range = [0, 6] # 第二个子图的X范围 ax1.set_xlim(x1_range) ax2.set_xlim(x2_range) # 4. 关键:设置坐标轴等比例,确保圆形显示为正圆 # adjustable='box'允许通过调整子图尺寸来满足等比例要求 ax1.set_aspect('equal', adjustable='box') ax2.set_aspect('equal', adjustable='box') # 5. 调整子图尺寸,让它们适配各自的X轴范围 # 计算每个子图需要的宽度比例:X范围长度 / Y范围长度 y_total_length = y_max - y_min width_ratio1 = (x1_range[1] - x1_range[0]) / y_total_length width_ratio2 = (x2_range[1] - x2_range[0]) / y_total_length # 手动调整子图位置和宽度,保证比例正确,同时留好间距 total_width_ratio = width_ratio1 + width_ratio2 left_margin = 0.1 right_margin = 0.9 bottom_margin = 0.1 top_margin = 0.9 spacing = 0.05 # 子图之间的间距 # 设置第一个子图的位置:[左, 下, 宽, 高] ax1_pos = [ left_margin, bottom_margin, width_ratio1 / total_width_ratio * (right_margin - left_margin), top_margin - bottom_margin ] ax1.set_position(ax1_pos) # 设置第二个子图的位置,注意加上第一个子图的宽度和间距 ax2_pos = [ left_margin + ax1_pos[2] + spacing, bottom_margin, width_ratio2 / total_width_ratio * (right_margin - left_margin), top_margin - bottom_margin ] ax2.set_position(ax2_pos) # 画两个圆验证效果(正圆就说明等比例生效了) ax1.add_patch(plt.Circle((0, 0), 2, color='crimson', fill=False, linewidth=2)) ax2.add_patch(plt.Circle((3, 0), 2, color='deepskyblue', fill=False, linewidth=2)) plt.show()
关键步骤解释
- 共享Y轴:用
sharey=True创建子图,这样只需要给其中一个子图设置Y轴范围,另一个会自动同步,避免重复操作。 - 等比例坐标轴:
set_aspect('equal', adjustable='box')是核心,它强制X/Y轴的单位长度相等,同时允许通过调整子图的尺寸来满足这个要求,这也是画正圆的关键。 - 适配X轴范围的子图尺寸:因为Y轴范围固定,我们通过计算X范围长度和Y范围长度的比例,来分配两个子图的宽度,这样每个子图的X轴范围刚好能填满子图宽度,不会出现留白或者挤压的情况。
- 灵活调整:如果你需要修改轴范围,只需要更新
y_min/y_max、x1_range/x2_range这几个变量就行,代码会自动重新计算宽度比例,不需要手动改子图尺寸。
内容的提问来源于stack exchange,提问作者Guiste
相关产品推荐
相关产品推荐

