Matplotlib叠加绘制分位数水平条形 解决标签重叠问题
分位数重叠分层条形图标签重叠问题解决方案
你当前标签全部重叠的核心原因是:三次调用bar_label时都绑定了ax.containers[0],也就是第一次绘制的p90条形容器,所有标签都被放在p90条形的中心位置,自然会完全重叠。
你从大到小依次叠加绘制水平条形的思路是完全可行的——分位数本身是嵌套关系(p50 < p75 < p90),先画最长的p90条,再叠稍短的p75条,最后叠最短的p50条,就能实现同一条形分层展示的效果,只需要修正标签绑定逻辑,再做简单的视觉优化即可。
实现步骤
- 提前对数据集做一次排序并保存结果,避免多次重复排序导致条形、标签的行顺序错位
- 按p90→p75→p50的顺序绘制水平条形,给三层配置区分度足够的同色系颜色,保证视觉分层清晰
- 按绘图顺序,依次给对应索引的条形容器绑定标签,标签文字颜色要和所在条形的底色有足够对比度,保证可读性
- 可选添加描边、调整图例位置优化展示效果
可直接运行的修正代码
import pandas as pd import matplotlib.pyplot as plt # 替换为你的数据读取逻辑 raw_data = [ ["A", 2.84, 5.7681, 2.72, 3.42, 4.090, 526181], ["B", 2.73, 6.3373, 2.57, 3.52, 4.360, 646022], ["C", 2.51, 21.4732, 1.67, 3.35, 5.442, 1140], ["D", 2.19, 9.3906, 1.87, 3.15, 3.430, 110729], ["E", 2.19, 5.6669, 2.00, 2.70, 3.630, 703413] ] df = pd.DataFrame( raw_data, columns=["customer", "avg_price", "avg_price2", "p_50", "p_75", "p_90", "count"] ) # 提前完成排序,固定行顺序 df_sorted = df.sort_values(by="avg_price").reset_index(drop=True) fig, ax = plt.subplots(figsize=(10, 7)) # 配置三层的颜色、对应文字颜色 layer_config = [ ("p_90", "#14325c", "white"), # 最底层p90:深蓝色+白字 ("p_75", "#3a73b3", "white"), # 中间层p75:中蓝色+白字 ("p_50", "#91c0ec", "black") # 最上层p50:浅蓝色+黑字 ] # 循环绘制三层条形,加白色描边强化分层边界 for col, bar_color, text_color in layer_config: df_sorted.plot.barh( x="customer", y=col, width=0.75, ax=ax, color=bar_color, edgecolor="white", linewidth=1.2, label=col ) # 按绘图顺序,给每一层的条形容器单独加标签 for layer_idx, (col, _, text_color) in enumerate(layer_config): label_text = [f"{val:.2f}" for val in df_sorted[col]] ax.bar_label( ax.containers[layer_idx], labels=label_text, label_type="center", color=text_color, fontweight="medium" ) # 基础美化 ax.set_xlabel("分位数值") ax.set_ylabel("客户分组") ax.legend(title="分位数类型", bbox_to_anchor=(1.01, 1), loc="upper left") plt.tight_layout() plt.show()
特殊情况调整
如果某组的两个分位数差值很小,标签出现挤在一起的情况,可以通过给bar_label加padding参数微调位置:
- 最底层p90的标签设置
padding=10,让文字稍微靠右 - 最上层p50的标签设置
padding=-10,让文字稍微靠左
即可在不改动条形结构的前提下错开重叠标签。
内容的提问来源于stack exchange,提问作者Geosphere
相关产品推荐
相关产品推荐

