Matplotlib 3D柱状图下方文本斜向对齐调整需求
解决Matplotlib 3D柱状图下方文本对齐与位置问题
你的问题核心是固定偏移量无法适配所有柱子的位置,且未设置文本旋转实现斜向对齐。以下是针对性的修改方案:
关键修改点
- 基于柱子的中心坐标定位文本,而非固定偏移,确保每个文本对应正确的柱子组
- 添加旋转参数实现斜向对齐,配合对齐参数保证排版整齐
- 调整z轴和y轴的偏移值,避免文本嵌入或远离柱子
修改后的完整代码
import matplotlib.pyplot as plt from matplotlib.lines import Line2D import numpy as np import pandas as pd color_dict = {'used': '#A54836', 'free': '#5375D4'} xy_ticklabel_color, xlabel_color, grand_totals_color, legend_color, grid_color, datalabels_color = '#101628',"#101628","#101628","#101628", "#C8C9C9", "#757C85" df = pd.DataFrame([ ['hd_xxxxxx-ppp-d2', 355, 237, 592], ['hd_disk_vvvvvvvv', 0, 184, 184], ['hd_aaaa-C_DDDDDDDDDDD', 0, 240, 240], ['hd_AAAAAAA_DDDDDDDDDDD', 1, 9, 10], ['hd_xxxxxx-ppp-d1', 870, 342, 1212], ['hd_aaaa_CC2-SSSS-01', 0, 9, 9], ['hd_aaaa_DD1-MMMM-01', 387, 286, 673], ['hd_wwww_DD2-MMMM-01', 437, 230, 667], ['hd_disk_bbbbbbbbbb', 0, 179, 179], ]) df.columns = ['disk_pool_name', 'used_space_kb', 'free_space_kb', 'total_capacity'] used = df[['disk_pool_name', 'used_space_kb']].rename(columns={"used_space_kb": "TB"}) used['status'] = 'used' free = df[['disk_pool_name', 'free_space_kb']].rename(columns={"free_space_kb": "TB"}) free['status'] = 'free' teste = pd.concat([used, free], axis=0, ignore_index=True, sort=False) teste = teste.sort_values(['disk_pool_name', 'status'], ascending=[True, False]) # map colors teste['colors']= teste.status.map(color_dict) dp_names = teste.disk_pool_name.unique() status = ['used', 'free'] nr_status = len(status) sub_totals = df.sort_values(['disk_pool_name'])['total_capacity'] colors = teste.colors dx = 100 dy = 100 dz = teste.TB.to_list() xs_separation = 250 ys_separation = 125 xs = np.repeat(np.arange(0, len(dp_names)) * xs_separation,len(status)).tolist() ys = np.repeat(np.arange(0, len(dp_names)) * ys_separation,len(status)).tolist() zs = np.array(teste.groupby('disk_pool_name', sort=False).TB.apply(list).tolist()) zs = np.cumsum(zs, axis=1)[:,:nr_status-1] zs = np.insert(zs, 0, 0, axis=1).flatten().tolist() fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(1, 1, 1, projection='3d') ax.bar3d(xs, ys, zs, dx, dy, dz, color=colors, label=status) for x, y, z, zdir in zip(xs, ys, zs, dz): label_point = zdir if zdir > 0 else '' ax.text(x - 1.5, y, z + zdir / 2, label_point, size=10, ha="right", color=datalabels_color) lines = [Line2D([0], [0], color=c, marker='s',linestyle='', markersize=10,) for c in reversed(colors.unique())] labels = teste.status.unique() plt.legend(lines, reversed(labels), labelcolor=legend_color, prop=dict(weight='bold', size=12), bbox_to_anchor=(0.5, -0.05), loc="lower center", ncols=2,frameon=False, fontsize=14) # 修改后的文本标注部分 for i, (dp, sub_total) in enumerate(zip(dp_names, sub_totals)): # 计算当前柱子组的中心坐标 base_x = xs[i * nr_status] + dx / 2 base_y = ys[i * nr_status] + dy / 2 # 斜向对齐文本,调整位置适配所有柱子 ax.text(base_x, base_y - 150, z=-50, s=f"{dp}", color=xy_ticklabel_color, weight="bold", fontsize=7, rotation=45, ha='right', va='top', zdir='y') ax.text(xs[i * nr_status] - 130, ys[i * nr_status] + 260, z=zs[i * nr_status] + sub_total + 2, s=f"{sub_total}", fontsize=10, weight="bold", color=grand_totals_color, bbox=dict(facecolor='none', edgecolor='#EBEDEE', boxstyle='round,pad=0.3')) ax.set_aspect("equal") plt.show()
说明
base_x和base_y以柱子组的左上角坐标加上半宽/半高,得到柱子中心位置,确保文本对应正确的柱子rotation=45实现斜向对齐,ha='right'和va='top'保证文本从右下角向左上方排列,避免重叠- 调整
base_y - 150和z=-50的数值可以进一步微调文本与柱子的间距,适配你的显示需求
内容的提问来源于stack exchange,提问作者André Amorim
相关产品推荐
相关产品推荐

