
本文介绍在 expense tracker 应用中正确绘制条形图的方法:当日期列表存在重复值(如多笔同日支出)时,避免 matplotlib 自动去重,确保每个数据点独立显示。
在开发个人记账应用时,常需可视化每日支出明细。但若直接将含重复日期的列表(如 ['2014-1-4', '2014-1-4', '2014-1-4', '2014-1-5'])传给 plt.bar(date, amount),Matplotlib 会将相同日期视为同一分类并合并(或仅保留一个刻度),导致条形数量少于实际交易数——这显然违背“每笔支出独立呈现”的设计初衷。
根本原因在于:plt.bar() 默认将 x 轴视为分类索引,当传入字符串列表时,它会对重复标签做隐式聚合,而非按位置逐个渲染。解决方案是解耦数据定位与标签显示:使用整数索引作为柱子的横坐标(保证一一对应),再通过 plt.xticks() 单独指定每个柱子下方显示的日期标签。
以下是推荐实现方式:
import matplotlib.pyplot as plt
# 示例数据:四笔交易,前三笔发生在同一天
date = ['2014-1-4', '2014-1-4', '2014-1-4', '2014-1-5']
amount = [100, 5000, 1000, 2000]
# 创建等长整数索引 [0, 1, 2, 3]
ind = list(range(len(date)))
# 绘制条形图:x 坐标为索引,y 值为金额
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(ind, amount, color='#4a90e2', alpha=0.8)
# 将每个索引位置标注对应日期(支持重复)
plt.xticks(ticks=ind, labels=date, rotation=30, ha='right')
# 添加基础图表元素
ax.set_ylabel('Amount (¥)')
ax.set_title('Daily Expense Breakdown')
ax.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()✅ 关键要点:
- ind = list(range(len(date))) 生成唯一位置索引,确保每笔交易都有独立柱子;
- plt.xticks(ticks=ind, labels=date) 显式绑定每个索引到其原始日期字符串,保留重复信息;
- rotation=30 和 ha='right' 提升长日期标签的可读性;
- 避免使用 plt.bar(date, amount) 直接绘图——这是导致去重的根源。
⚠️ 注意事项:
- 若数据量较大(如数百条),建议对 x 轴标签做分组聚合(如按周/月汇总),否则图表将过于拥挤;
- 如需进一步区分同日多笔交易,可在标签中加入序号(如 '2014-1-4 #1'),或改用散点图+误差线;
- 在 Web 应用(如 Flask/Django)中嵌入图表时,请使用 FigureCanvasAgg 渲染为 PNG 或集成 Plotly 实现交互式缩放。
该方法轻量、可靠,完美适配记账类应用中“按原始记录粒度展示”的核心需求。










