Matplotlib 3D绘图:如何让茎图显示在2D等高填充图前方?
解决方案
问题根源
Matplotlib的3D坐标轴渲染优先级由元素的z坐标决定,而非zorder参数。原代码中contourf和茎图的底部都在z=0层级,导致茎被遮挡。此外,默认茎图样式较细,需调整以接近柱状图效果。
修复后的茎图版本代码
import numpy as np import matplotlib.pyplot as plt x = np.linspace(-1, 1, 101) y = np.linspace(-1, 1, 101) X, Y = np.meshgrid(x, y) z = np.exp(-(X**2) - Y**2) x0 = [-0.5, 0, 0.5] y0 = [-0.5, 0, 0.5] z0 = [0.5, 1, 2] fig, ax = plt.subplots(subplot_kw=dict(projection="3d")) # 将等高填充图置于z=-0.01层级,低于茎的起始位置z=0 ax.contourf( x, y, z, zdir="z", offset=-0.01, cmap='viridis' ) # 绘制茎图,隐藏基线并加粗茎条 ps = ax.stem(x0, y0, z0, basefmt=" ", linefmt="k-", markerfmt="ko") ps[0].set_linewidth(8) # 调整茎宽,贴近柱状图视觉效果 # 设置坐标轴标签 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show()
柱状图替代方案
若需要完全的柱状图效果,可使用bar3d替代stem:
import numpy as np import matplotlib.pyplot as plt x = np.linspace(-1, 1, 101) y = np.linspace(-1, 1, 101) X, Y = np.meshgrid(x, y) z = np.exp(-(X**2) - Y**2) x0 = [-0.5, 0, 0.5] y0 = [-0.5, 0, 0.5] z0 = [0.5, 1, 2] dx = dy = 0.1 # 柱子的x、y方向宽度 fig, ax = plt.subplots(subplot_kw=dict(projection="3d")) ax.contourf( x, y, z, zdir="z", offset=-0.01, cmap='viridis' ) # 从z=0起始绘制3D柱状图 for xi, yi, zi in zip(x0, y0, z0): ax.bar3d(xi - dx/2, yi - dy/2, 0, dx, dy, zi, color='k', alpha=0.7) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show()
关键调整说明
- 将
contourf的offset设为-0.01,让等高图处于茎/柱子下方,避免遮挡。 - 茎图中用
basefmt=" "隐藏默认基线,调整linewidth加粗茎条。 - 柱状图通过
bar3d直接绘制带宽度的柱子,完全贴合需求。
内容的提问来源于stack exchange,提问作者mmonti
相关产品推荐
相关产品推荐

