Matplotlib中2D与3D子图高度不等的原因及统一解决方案?
混合绘制2D与3D子图时边界框高度不一致的原因及解决方案
这个问题我之前也碰到过,其实是matplotlib对2D和3D轴的布局逻辑差异导致的,下面给你拆解原因和解决办法:
现象原因
- 3D轴的空间预留机制:matplotlib的3D轴默认会为3D视角交互(比如旋转)、z轴元素(标签、刻度)预留额外的边界空间,即使你没有启用交互式旋转,这个预留空间依然会被计算到边界框中,导致3D子图的实际可绘图区域高度和2D子图不匹配。
- 2D轴的紧凑布局逻辑:2D轴的边界框是严格基于x/y轴元素、绘图内容的尺寸来计算的,没有额外的3D空间预留,所以它的高度通常会比同布局下的3D轴更贴合实际绘图区域。
简便解决方法
我们可以手动统一两个子图的位置和高度,利用matplotlib的轴位置API就能轻松实现:
- 绘制完所有子图后,分别获取2D轴和3D轴的位置参数(格式为
[left, bottom, width, height]) - 以其中一个轴的高度和垂直位置为基准,调整另一个轴的位置,让两者的底部对齐且高度一致
- 用
set_position()应用调整后的位置
修改后的代码示例
import numpy as np import matplotlib.pyplot as plt import matplotlib.tri as mtri u = np.linspace(0, 2.0 * np.pi, endpoint=True, num=50) v = np.linspace(-0.5, 0.5, endpoint=True, num=10) u, v = np.meshgrid(u, v) u, v = u.flatten(), v.flatten() x = (1 + 0.5 * v * np.cos(u / 2.0)) * np.cos(u) y = (1 + 0.5 * v * np.cos(u / 2.0)) * np.sin(u) z = 0.5 * v * np.sin(u / 2.0) tri = mtri.Triangulation(u, v) fig = plt.figure(figsize=plt.figaspect(0.5)) # 绘制2D子图 ax2d = fig.add_subplot(1, 2, 1) ax2d.plot(x, y) # 绘制3D子图 ax3d = fig.add_subplot(1, 2, 2, projection='3d') ax3d.plot_trisurf(x, y, z, triangles=tri.triangles, cmap=plt.cm.Spectral) ax3d.set_zlim(-1, 1) # 统一两个子图的边界框高度和位置 pos2d = ax2d.get_position() pos3d = ax3d.get_position() # 以2D子图的高度和底部位置为基准,调整3D子图 new_pos3d = [pos3d.x0, pos2d.y0, pos3d.width, pos2d.height] ax3d.set_position(new_pos3d) plt.show()
这样调整后,两个子图的边界框高度就会完全一致了。你也可以根据需求选择以3D子图的高度为基准调整2D子图,只需要把基准换成pos3d即可。
内容的提问来源于stack exchange,提问作者mins
相关产品推荐
相关产品推荐

