背景介绍
在个人财务管理中,清晰的支出分析是优化消费习惯的关键。手动统计月度支出不仅耗时,还容易出错。本文将介绍如何用Python开发一个个人月度支出分析工具,自动从CSV支出记录中提取关键信息:按类别统计支出、生成可视化图表、输出分析报告,帮助你快速掌握支出结构。
思路分析
工具的核心流程分为四步:
1. 数据读取:用pandas读取CSV格式的支出记录;
2. 统计分析:按“类别”分组求和,计算总支出、类别占比、排名等;
3. 可视化输出:用matplotlib绘制饼图(占比)和柱状图(金额);
4. 报告生成:将统计结果整理成文本报告,输出到文件。
代码实现(完整可运行)
以下是完整代码,包含详细注释:
import pandas as pd
import matplotlib.pyplot as plt
# 解决matplotlib中文显示问题(需系统安装SimHei字体)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def analyze_expenses(csv_path):
"""
分析月度支出:读取CSV→统计→可视化→生成报告
:param csv_path: CSV文件路径(格式:日期,类别,金额)
"""
# 1. 读取CSV数据
try:
df = pd.read_csv(csv_path)
# 确保金额为数值类型(若CSV中金额是字符串,可取消下面的注释)
# df['金额'] = df['金额'].astype(float)
except Exception as e:
print(f"读取CSV失败:{e}")
return
# 2. 统计分析:总支出、类别金额、占比、排序
total_expense = df['金额'].sum() # 总支出
# 按类别分组,计算总金额
category_stats = df.groupby('类别')['金额'].sum().reset_index()
category_stats = category_stats.rename(columns={'金额': '总金额'}) # 重命名列
# 计算占比(保留2位小数)
category_stats['占比(%)'] = (category_stats['总金额'] / total_expense * 100).round(2)
# 按金额降序排序(支出高的类别排前)
category_stats = category_stats.sort_values(by='总金额', ascending=False)
# 3. 可视化:饼图(类别占比)
plt.figure(figsize=(8, 8))
sizes = category_stats['总金额']
# 生成标签:类别+金额+占比
labels = [f"{row['类别']}\n{row['总金额']}元\n{row['占比(%)']}%"
for _, row in category_stats.iterrows()]
plt.pie(sizes, labels=labels, autopct='%1.2f%%', startangle=90)
plt.title('月度支出类别占比')
plt.axis('equal') # 保证饼图为正圆形
plt.savefig('expense_pie.png') # 保存饼图
plt.close()
# 可视化:柱状图(类别金额)
plt.figure(figsize=(10, 6))
x = category_stats['类别']
y = category_stats['总金额']
bars = plt.bar(x, y, color='skyblue')
plt.title('月度支出类别金额')
plt.xlabel('支出类别')
plt.ylabel('金额(元)')
plt.xticks(rotation=45) # 旋转类别标签,防止重叠
# 标注柱子上方的金额
for bar in bars:
height = bar.get_height()
plt.text(
bar.get_x() + bar.get_width() / 2,
height + 1, # 金额标签在柱子上方1单位
f'{height}元',
ha='center',
va='bottom'
)
plt.tight_layout() # 自动调整布局,防止标签截断
plt.savefig('expense_bar.png') # 保存柱状图
plt.close()
# 4. 生成文本报告
# 提取年月(从第一条记录的日期中获取)
first_date = df['日期'].iloc[0]
year, month, _ = first_date.split('-')
# 类别数量、最高支出类别、平均日支出
category_count = len(category_stats)
top_category = category_stats.iloc[0]['类别']
top_amount = category_stats.iloc[0]['总金额']
avg_daily = total_expense / 30 # 按30天计算平均日支出
# 构建报告内容
report = f"""=====================================
个人月度支出分析报告({year}年{month}月)
=====================================
总支出金额:{total_expense} 元
支出类别数量:{category_count} 类({', '.join(category_stats['类别'])})
各类别支出详情(按金额从高到低排序):
"""
for i, (_, row) in enumerate(category_stats.iterrows(), 1):
report += f"{i}. {row['类别']}:{row['总金额']} 元,占比 {row['占比(%)']}%\n"
report += f"""
支出最高的类别:{top_category}({top_amount} 元)
平均每日支出:{avg_daily:.2f} 元(按30天计算)
=====================================
"""
# 写入报告到文件
with open('expense_analysis.txt', 'w', encoding='utf-8') as f:
f.write(report)
print("分析完成!已生成:")
print("- 饼图:expense_pie.png")
print("- 柱状图:expense_bar.png")
print("- 分析报告:expense_analysis.txt")
if __name__ == "__main__":
# 替换为你的CSV文件路径(示例:monthly_expenses.csv)
csv_path = "monthly_expenses.csv"
analyze_expenses(csv_path)
代码解析
1. 数据读取与统计
- CSV读取:
pd.read_csv()自动解析CSV文件,需确保列名与代码一致(日期、类别、金额)。 - 分组统计:
groupby('类别')按“类别”分组,sum()计算总金额;round(2)保留占比的两位小数。 - 排序:
sort_values(by='总金额', ascending=False)按金额降序排列,方便后续报告生成。
2. 可视化定制
- 饼图:通过列表推导式生成标签(包含类别、金额、占比),
autopct='%1.2f%%'显示百分比;axis('equal')保证饼图为正圆形。 - 柱状图:
xticks(rotation=45)旋转类别标签防止重叠;plt.text()在柱子上方标注金额,提升可读性。
3. 报告生成
- 日期提取:从第一条记录的日期中拆分出“年”和“月”,使报告更规范。
- 内容拼接:按格式拼接总支出、类别数量、排序后的类别详情、最高支出、平均日支出。
- 文件写入:
with open()保证文件安全写入,encoding='utf-8'支持中文。
测试与验证
将示例CSV文件(monthly_expenses.csv)放在代码同目录下,运行后:
– 饼图(expense_pie.png):扇区对应类别,标签包含金额和占比。
– 柱状图(expense_bar.png):柱子高度与金额一致,上方标注数值。
– 报告(expense_analysis.txt):总支出、类别排序、最高支出等信息与实际计算一致。
扩展与优化
- 多文件支持:遍历文件夹,合并多个CSV文件的支出记录。
- 动态天数:从日期列计算实际天数,替代固定的30天。
- 收入分析:扩展CSV格式,增加“收入/支出”列,支持收入统计。
总结
本工具将数据读取→统计分析→可视化→报告生成串联,实践了Python在个人财务管理中的应用。通过pandas的数据分组、matplotlib的可视化定制,你不仅能掌握Python技能,还能为个人理财提供实用工具。快用它分析你的支出,优化消费习惯吧!
(注:若运行时中文乱码,需确保matplotlib的字体设置正确;若CSV格式异常,需检查列名和数据类型。)