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

Matplotlib绘制含多子图的DataFrame柱状图技术问询

基于月度分组数据绘制嵌套柱状图

原始数据

Date & Time  Amount   Count
Aug 2022    $10.50     53
            $14.00      1
            $3.50     416
            $35.00    186
Jul 2022    $14.00      1
            $3.50     844
            $35.00    307
Jun 2022    $14.00      1
            $3.50     797
            $35.00    323

需求

用Matplotlib绘制图表:主X轴为年月,每个年月下以金额(Amount)为子X轴,Y轴展示对应计数(Count),解决不同月份Amount数量不一致的布局问题。

解决方案

1. 数据预处理

先补全数据结构,清理金额列的符号并转为数值类型:

import pandas as pd
import matplotlib.pyplot as plt

# 构建示例DataFrame
data = [
    ["Aug 2022", "$10.50", 53],
    ["Aug 2022", "$14.00", 1],
    ["Aug 2022", "$3.50", 416],
    ["Aug 2022", "$35.00", 186],
    ["Jul 2022", "$14.00", 1],
    ["Jul 2022", "$3.50", 844],
    ["Jul 2022", "$35.00", 307],
    ["Jun 2022", "$14.00", 1],
    ["Jun 2022", "$3.50", 797],
    ["Jun 2022", "$35.00", 323]
]

df = pd.DataFrame(data, columns=["Date & Time", "Amount", "Count"])
# 清理金额列,转为数值
df["Amount"] = df["Amount"].str.replace("$", "").astype(float)
# 按月份分组
month_groups = df.groupby("Date & Time")

2. 绘制动态宽度的嵌套柱状图

核心是为每个月份分配主X轴位置,再根据该月的Amount数量动态调整子柱子宽度,避免重叠:

# 设置画布
fig, ax = plt.subplots(figsize=(10, 6))
# 主X轴的位置和月份标签
month_labels = list(month_groups.groups.keys())
month_positions = range(len(month_labels))
# 每个月份组占用的总宽度
total_group_width = 0.8

# 遍历每个月份分组
for month_idx, (month, group) in enumerate(month_groups):
    # 对该月的金额排序,保证柱子顺序一致
    sorted_group = group.sort_values("Amount")
    amounts = sorted_group["Amount"]
    counts = sorted_group["Count"]
    
    num_bars = len(amounts)
    # 计算每个子柱子的宽度和位置
    bar_width = total_group_width / num_bars
    sub_positions = [month_positions[month_idx] - total_group_width/2 + bar_width*(i + 0.5) for i in range(num_bars)]
    
    # 绘制柱子
    bars = ax.bar(sub_positions, counts, width=bar_width)
    # 在柱子上方标注计数
    for bar in bars:
        height = bar.get_height()
        ax.text(bar.get_x() + bar.get_width()/2, height,
                f"{int(height)}", ha="center", va="bottom")

# 设置主X轴刻度和标签
ax.set_xticks(month_positions)
ax.set_xticklabels(month_labels)
# 设置轴标签和标题
ax.set_xlabel("年月")
ax.set_ylabel("计数")
ax.set_title("各月不同金额的计数分布")

# 添加金额图例
unique_amounts = sorted(df["Amount"].unique())
from matplotlib.patches import Patch
legend_handles = [Patch(facecolor=plt.cm.tab10(i), label=f"${amt:.2f}") for i, amt in enumerate(unique_amounts)]
ax.legend(handles=legend_handles, title="金额")

plt.tight_layout()
plt.show()

效果说明

  • 每个月份的柱子总宽度固定,子柱子宽度随该月Amount数量自动调整,保证布局紧凑且不重叠
  • 金额按从小到大排序,不同月份的同金额柱子颜色统一,便于对比
  • 柱子上方标注具体计数,数据展示更直观

内容的提问来源于stack exchange,提问作者javery1337

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:54:22