Python 环境加载中…

综合项目一:分析一年的记账本

3 道练习题·预计 60 分钟·做对一题解锁下一段

完整通读本章 →

教学 01 / 10· 已读

前言

八章学下来,读进来、看清楚、挑出来、洗干净、算一算、拼起来、画出来,做数据分析的零件都已经齐了。零件齐了,能拼出什么来呢?这一章不学新东西,就用这些零件做一个完整的分析,回答一个问题:2026 年这一年的钱,花得怎么样?

还记得第 1 章说的六个步骤吗?提问、获取、清洗、探索、分析、结论。前面每一章,练的都只是其中的一两步;这一章,咱们要从头走到尾。

具体怎么走呢?和爬虫课的综合项目一样,节奏是这样的:先把问题拆清楚,再一个问题一个问题地算;每算出一个数,都检查一下对不对;最后,把结论写成一份别人看得懂的报告。

学这一章之前,需要先学完数据分析课第 1~8 章,尤其是 第 6 章 的分组汇总和 第 8 章 的画图。

目录

这一章会做:

  • 一、提问——把「花得怎么样」拆成五个具体的问题
  • 二、获取和检查——写一个 load() 函数
  • 三、一共花了多少,花在哪儿
  • 四、哪几个月花得多,为什么
  • 五、吃饭和周末
  • 六、写成一份报告
  • 七、常见坑
  • 八、自己查一次文档——用 pct_change() 算比上个月多了多少
  • 九、小结与回看

做完这一章,你会有一份从数据里一步步推出来、每个数都经得起追问的分析报告。

教学 02 / 10· 已读

一、提问

「今年的钱花得怎么样?」这个问题,能直接拿数据来回答吗?其实不能,因为它太笼统了,不知道该算什么。第 1 章说过,碰到这种问题,要先把它变成一个个能用数据回答的具体问题。

那该怎么拆呢?可以拆成下面这五个:

问题要算的数用到的本事
1. 一年一共花了多少,平均每月多少?总额、月平均sum()
2. 钱主要花在哪儿?各类别的金额和占比groupby() 、比例
3. 哪几个月花得多?多在哪儿?每月金额,每月各类别金额dt.month 、pivot_table() 、画图
4. 吃饭花了多少?三顿饭里哪顿最该省?三餐的笔数、合计、平均筛选、agg()
5. 周末是不是比工作日花得多?周末、工作日每天平均花多少dt.dayofweek 、分组

你看,拆完以后,每个问题要算什么数、用哪个方法,就都清楚了。

不过,拆问题的时候,还有两件事值得想一想:

  • 这份数据能回答吗? 比如「钱花得值不值」,账本里没有收入,也不知道每样东西买得开不开心,就回答不了。只有能答的,才放进清单。
  • 答出来有什么用? 比如问题 4、5,都指向同一件事:要是想省钱,该从哪儿下手。所以问题不是越多越好,每一个都要能帮你做决定。

问题拆好了,接下来就照着这张表,一个一个地算。不过在算之前,得先把数据读进来,看看它靠不靠得住。

教学 03 / 10· 已读

二、获取和检查

五个问题,每一个都要先读进记账本,再把日期变成真正的日期。同样的几行代码,与其每次都写一遍,不如把它们写成一个函数:

Python· 可在网页运行
import pandas as pd


def load(path):
    """读进记账本,加上月份、是否周末两列"""
    ledger = pd.read_csv(path)
    ledger['date'] = pd.to_datetime(ledger['date'])
    ledger['month'] = ledger['date'].dt.month
    ledger['weekend'] = ledger['date'].dt.dayofweek >= 5
    return ledger


ledger = load('ledger_2026.csv')
print(ledger.head(3))

输出的结果:

文本
        date      item category    cost payment  month  weekend
0 2026-01-01      房租     居住  2500.0  银行卡      1    False
1 2026-01-01  水电燃气     居住   156.0  支付宝      1    False
2 2026-01-01      早饭     餐饮    13.0  支付宝      1    False

函数里除了读文件、转日期,还多加了两列,都是给后面的问题准备的:

  • month 是月份,问题 3 要用。
  • weekend 用的是第 5 章学的 dt.dayofweek :5 是星期六,6 是星期日,大于等于 5 就是周末。比较的结果,是一串 True 和 False 。问题 5 要用到它。

数据读进来了,可先别急着算。第 5 章说过,拿到数据的第一件事,是给它做个体检:

Python· 可在网页运行
import pandas as pd


def load(path):
    """读进记账本,加上月份、是否周末两列"""
    ledger = pd.read_csv(path)
    ledger['date'] = pd.to_datetime(ledger['date'])
    ledger['month'] = ledger['date'].dt.month
    ledger['weekend'] = ledger['date'].dt.dayofweek >= 5
    return ledger


ledger = load('ledger_2026.csv')
print(len(ledger), ledger.isna().sum().sum(), ledger.duplicated().sum())
print(ledger['date'].min(), ledger['date'].max(), ledger['date'].nunique())
print(ledger['cost'].min(), ledger['cost'].max())

输出的结果:

文本
1354 0 0
2026-01-01 00:00:00 2026-12-31 00:00:00 365
3.0 2500.0

三行输出,咱们一行一行地看:

  • 第一行:一共 1354 笔,没有空值,也没有重复的行。这里的 isna().sum() 算出的是每一列的空值个数,再 sum() 一次,就是整张表一共有几个空值。
  • 第二行:日期从 1 月 1 日到 12 月 31 日,一共 365 个不同的日子。也就是说,每天都记了账,没有漏掉的日子。
  • 第三行:金额最少 3 元,最多 2500 元,那是房租。没有负数,也没有离谱的值。

体检下来,这份账本是干净的,可以放心地分析了。要是体检发现了问题,就该先用第 5 章的办法,把数据洗干净再说。

另外,把读数据写成 load() 函数,还有一个好处:明年有了 ledger_2027.csv ,只要换一个文件名,后面的分析一行都不用改。

数据准备好了,下一节就从最基本的两个问题算起。

教学 04 / 10

三、一共花了多少,花在哪儿

先算问题 1 和问题 2:一年一共花了多少?钱主要花在哪儿?这两个问题都要用到全年的总额,所以放在一起算:

Python· 可在网页运行
import pandas as pd


def load(path):
    """读进记账本,加上月份、是否周末两列"""
    ledger = pd.read_csv(path)
    ledger['date'] = pd.to_datetime(ledger['date'])
    ledger['month'] = ledger['date'].dt.month
    ledger['weekend'] = ledger['date'].dt.dayofweek >= 5
    return ledger


ledger = load('ledger_2026.csv')
total = ledger['cost'].sum()
print(f'全年合计 {total:,.1f} 元,平均每月 {total / 12:,.1f} 元')

by_category = ledger.groupby('category')['cost'].sum().sort_values(ascending=False)
share = (by_category / total).round(3)
print(share)
print(share.sum())

输出的结果:

文本
全年合计 69,195.5 元,平均每月 5,766.3 元
category
居住    0.475
餐饮    0.341
购物    0.072
娱乐    0.046
交通    0.025
学习    0.024
医疗    0.017
Name: cost, dtype: float64
1.0

代码里有两处值得说一说:

  • by_category / total :一个 Series 除以一个数,每个值都会除一遍,得到的就是各类别的占比。注意,它和第 4 章的 value_counts(normalize=True) 不一样:那个是按笔数算的比例,这里是按金额算的。
  • 最后打印 share.sum() ,是顺手做个检查:占比加起来应该是 1。这回正好是 1.0,没有多也没有少。每算出一组数,都找一个办法验一验,这是这一章要养成的习惯。

数都验过了,可以下结论了:

  • 一年花了将近 7 万元,平均每月五千七百多元。
  • 居住占了将近一半,47.5%。房租、水电这些是固定开销,每个月都得交,短期内很难省下来。
  • 吃饭占了三分之一,34.1%。剩下的购物、娱乐、交通、学习、医疗,加起来还不到两成。

这告诉我们:真想省钱,能动的主要就是吃饭和购物这两块。

知道了钱花在哪儿,下一节接着看钱是什么时候花的:哪几个月花得多?在那之前,先做一道练习,算一算吃饭和购物这两块一共占了多少。

练习 1 / 3能省的两块占多少题目有问题?

第三节说,能省的主要是吃饭和购物。用 load() 读进记账本,按类别汇总,分两行打印:购物占全年花销的比例,餐饮加购物一共占的比例。都用 f-string 的 :.1% 格式。

运行后的输出应该是:

文本
7.2%
41.3%
main.py
可编辑
做对当前题解锁下一段 ·03

推荐一个,全网最全最友好的中文 AI 编程指南: coding.stormzhang.ai

学习目录