You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:07:03