Matplotlib共享轴子图设置单图轴比例问题求助
Matplotlib共享轴子图的轴比例设置解决方案
我有一个2×2的Matplotlib子图布局,其中三个子图共享轴:顶部直方图(ax[0,0])、右侧直方图(ax[1,1])和中心二维直方图(ax[1,0])。想要为中心的二维直方图设置等轴比例,但尝试使用box_aspect的方法后,要么只影响单个子图,要么打乱整体布局。
原代码(补全缺失的numpy导入):
import matplotlib.pyplot as plt from scipy.stats import norm import numpy as np fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(12, 8), gridspec_kw={'width_ratios': [3, 1], 'height_ratios': [1, 3], 'wspace': 0.0, 'hspace': 0.0}, sharex='col', sharey='row', subplot_kw=(dict(box_aspect=1) if False else None)) # 启用后布局混乱 x, y = norm.rvs(size=10000), norm.rvs(size=10000) ax[0][0].hist(x, bins=30) ax[1][1].hist(y, bins=30, orientation='horizontal') ax[1][0].hist2d(x, y, bins=[np.linspace(-4, 4, 30), np.linspace(-4, 4, 30)]) plt.show()
问题根源
sharex='col'和sharey='row'会强制同列/同行的子图轴范围和尺寸同步,而box_aspect或set_aspect('equal')会修改子图的宽高比例,两者冲突导致布局错乱。
解决方案1:调整布局比例适配等轴要求
通过修改figsize和gridspec的比例,让中心子图的原生宽高相等,再设置等轴比例,避免冲突:
import matplotlib.pyplot as plt from scipy.stats import norm import numpy as np # 设为正方形画布,配合gridspec比例让中心子图宽高相等 fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(10, 10), gridspec_kw={'width_ratios': [3, 1], 'height_ratios': [1, 3], 'wspace': 0.0, 'hspace': 0.0}, sharex='col', sharey='row') x, y = norm.rvs(size=10000), norm.rvs(size=10000) x_bins = np.linspace(-4, 4, 30) y_bins = np.linspace(-4, 4, 30) ax[0][0].hist(x, bins=x_bins) ax[1][1].hist(y, bins=y_bins, orientation='horizontal') ax[1][0].hist2d(x, y, bins=[x_bins, y_bins]) # 为中心子图设置等轴比例,此时宽高原生相等,不会挤压其他子图 ax[1,0].set_aspect('equal', adjustable='box') plt.show()
解决方案2:手动同步轴范围,放弃自动共享
不依赖Matplotlib的sharex/sharey,手动同步轴范围并隐藏多余刻度,自由设置中心子图比例:
import matplotlib.pyplot as plt from scipy.stats import norm import numpy as np fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(12, 8), gridspec_kw={'width_ratios': [3, 1], 'height_ratios': [1, 3], 'wspace': 0.0, 'hspace': 0.0}) x, y = norm.rvs(size=10000), norm.rvs(size=10000) x_bins = np.linspace(-4, 4, 30) y_bins = np.linspace(-4, 4, 30) ax[0][0].hist(x, bins=x_bins) ax[1][1].hist(y, bins=y_bins, orientation='horizontal') ax[1][0].hist2d(x, y, bins=[x_bins, y_bins]) # 手动同步所有子图的轴范围 x_min, x_max = x_bins.min(), x_bins.max() y_min, y_max = y_bins.min(), y_bins.max() ax[0,0].set_xlim(x_min, x_max) ax[1,0].set_xlim(x_min, x_max) ax[1,0].set_ylim(y_min, y_max) ax[1,1].set_ylim(y_min, y_max) # 隐藏多余刻度,模拟共享轴的视觉效果 ax[0,0].tick_params(axis='x', labelbottom=False) ax[1,1].tick_params(axis='y', labelleft=False) # 自由设置中心子图的等轴比例,不影响其他子图 ax[1,0].set_aspect('equal') plt.show()
内容的提问来源于stack exchange,提问作者Mister Mak
相关产品推荐
相关产品推荐

