Matplotlib 3.8中设置3D堆叠柱状图宽高比的问题
3D堆叠柱状图宽高比调整问题解决
问题描述
我想用Matplotlib绘制特定样式的3D堆叠柱状图,已编写初步代码并得到基础效果,但尝试调整宽高比时,使用set_aspect('equal', adjustable='datalim')未能达到预期。
初始实现代码
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np import pandas as pd colors = [ "#2B314D", "#A54836","#5375D4", ] data = { "year": [2004, 2022, 2004, 2022, 2004, 2022], "countries" : ["Sweden", "Sweden", "Denmark", "Denmark", "Norway", "Norway"], "sites": [13,15,5,8,4,10] } df= pd.DataFrame(data) df['year_lbl'] ="'"+df['year'].astype(str).str[-2:].astype(str) nr_countries = df.countries.nunique() nr_years = df.year.nunique() years = df.year.unique() x= [1,1,1] y=[0,0,0] z= [0,0,0] dx= [1,1,1] dy= [1,1,1] fig = plt.figure(figsize=(15,10)) for i,yrs in zip(range(0,nr_years), years): # Add the i+1 subplot of the x.shape[0] x 1 grid ax = fig.add_subplot(1,nr_years, i+1, projection='3d') temp_df = df[df.year == yrs] dz = temp_df.sites.tolist() _zpos = z # the starting zpos for each bar for i, c in zip(range(nr_countries), colors): ax.bar3d(x,y,_zpos,dx,dy,dz[i],color= c) _zpos += np.array(dz[i]) # add the height of each bar to know where to start the next ax.set_axis_off()
尝试调整的代码片段
ax.set_ylim(0,15) ax.set_xlim(0,15) ax.set_zlim(0,25) ax.set_aspect('equal', adjustable='datalim')
问题分析与解决
核心问题
- 3D轴
set_aspect逻辑特殊:Matplotlib 3D轴的equal比例设置和2D逻辑完全不同,因为3D视图涉及投影转换,单纯靠数据范围调整无法实现目标的扁平宽高比。 - 轴范围设置不合理:你的数据中x、y的实际取值范围极小(x固定为1,y固定为0),却设置了0-15的大范围,导致柱状图在轴上占比极低,视觉比例严重失调。
- 未控制3D视角:目标图的扁平效果核心来自特定的侧面视角,而非单纯的轴比例设置。
修正后的完整代码
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np import pandas as pd colors = [ "#2B314D", "#A54836","#5375D4", ] data = { "year": [2004, 2022, 2004, 2022, 2004, 2022], "countries" : ["Sweden", "Sweden", "Denmark", "Denmark", "Norway", "Norway"], "sites": [13,15,5,8,4,10] } df= pd.DataFrame(data) df['year_lbl'] ="'"+df['year'].astype(str).str[-2:].astype(str) nr_countries = df.countries.nunique() nr_years = df.year.nunique() years = df.year.unique() # 固定柱子的x、y基准位置 x= [1] * nr_countries y= [0] * nr_countries z= [0] * nr_countries dx= [1] * nr_countries # 柱子宽度 dy= [3] * nr_countries # 增大深度值,让柱子呈现扁平效果 fig = plt.figure(figsize=(12, 5)) # 调整画布宽高比,贴合目标横向布局 for i,yrs in zip(range(nr_years), years): ax = fig.add_subplot(1, nr_years, i+1, projection='3d') temp_df = df[df.year == yrs] dz = temp_df.sites.tolist() _zpos = z.copy() for idx, c in enumerate(colors): ax.bar3d(x[idx], y[idx], _zpos[idx], dx[idx], dy[idx], dz[idx], color=c) _zpos[idx] += dz[idx] # 缩小轴范围,匹配柱子实际尺寸,避免多余空白 ax.set_xlim(0.5, 1.5) ax.set_ylim(-1.5, 1.5) ax.set_zlim(0, sum(dz) + 2) # 调整3D视角,实现侧面扁平的视觉效果 ax.view_init(elev=25, azim=-65) ax.set_axis_off() plt.tight_layout() plt.show()
关键调整说明
- 增大柱子深度(dy):直接调整柱子的y轴方向尺寸,让柱子本身呈现扁平形态。
- 精准设置轴范围:只保留柱子所在的小范围轴区间,避免空白区域稀释视觉比例。
- 自定义3D视角:通过
view_init调整仰角(elev)和方位角(azim),让柱子以侧面角度展示,这是实现目标样式的核心。 - 优化画布比例:设置更宽的画布尺寸,让两个子图并排时贴合目标的横向布局。
内容的提问来源于stack exchange,提问作者ruthpozuelo
相关产品推荐
相关产品推荐

