数据分析在做什么

完整讲解 · 8 段教学·配 3 道练习题·预计 40 分钟

本页是本章的通读版,可直接读完全部讲解。想动手写代码、跑判分,去 闯关模式。

教学 01 / 08

前言

各位童鞋学到这里,手里其实已经攒了不少数据:实战 6 的记账本,记下了每一笔花销;学过爬虫课的童鞋,还从书店网站上抓下了一整个书店的图书。

数据是有了,可光把它们存着,并没有什么用。咱们真正想知道的是:这些数据能告诉我们什么?

比如,一年下来,钱主要花在了哪儿?哪个月花得最多?书店里,贵的书评分会不会更高?这些问题的答案,其实就藏在数据里。把答案找出来的过程,就叫数据分析。

那么,拿什么来做数据分析呢?这门课一共 10 章,用的是 Python 里做数据分析最常用的两个工具:

  • pandas:把数据装进一张「表」里。筛选、统计、分组、合并,几行代码就能搞定。
  • matplotlib:把数字画成图,让人一眼就看出趋势和差别。

练习用的数据有两份,都是编出来的:一份是 2026 年一整年的记账本,另一份是两点书店的图书和读者评分。前 8 章一样一样地学工具,最后两章是两个完整的分析项目,每个项目都要写出一份分析结论。

有一件事要先说在前面:pandas 和 matplotlib 加起来有几十 MB,第一次运行代码时,网页要先把它们下载下来。这时候输出区会显示下载进度,请耐心等一会儿。下载过一次以后,浏览器就记住了,下次不用再等这么久。

最后还想说一句。学数据分析,最怕的其实不是不会写代码,而是算出一个数,就急着下结论。所以这门课在教每一样工具的同时,还会一直追问两个问题:这个数说明了什么?它会不会骗了你?

学这一章之前,需要先学完基础课的第 0~9 章和实战 1~6,尤其是 实战 5 里的 csv 文件读写,这一章马上就会用到。爬虫课没学过也不要紧:最后一个项目要用到爬虫抓下的数据,网站已经提前替你准备好了。

目录

这一章会学到:

  • 一、从一个问题开始——什么样的问题能用数据回答
  • 二、数据分析的六步——提问、获取、清洗、探索、分析、结论
  • 三、先用学过的办法算一算——csv 模块加字典
  • 四、换成 pandas 试试——同样的事,三行代码
  • 五、常见坑
  • 六、自己查一次文档——pandas 的说明书在哪儿
  • 七、小结与回看

学完这一章,你会知道数据分析要做哪几件事,并用 pandas 读进第一份数据、算出第一个结果。

教学 02 / 08

一、从一个问题开始

拿到一份数据,很多童鞋的第一反应是:赶紧写代码,算点什么出来。其实先别急,第一件事应该是想清楚:我到底想知道什么?

比如手里有一年的记账本,你对自己说:「分析一下我的账。」这算不算一个问题呢?其实不算。因为它太笼统了,根本不知道该从哪儿下手:是算一共花了多少?还是看哪一类花得最多?

好的问题,要具体到能用数据回答。对比一下就清楚了:

笼统的具体的
我花钱多不多?2026 年一共花了多少?平均每个月多少?
钱都去哪儿了?每个类别各花了多少,哪个类别最多?
我是不是乱花钱?单笔超过 200 元的花销有几笔,都是什么?
周末是不是花得多?周末平均每天花多少,工作日平均每天花多少?

那么,右边这些具体的问题,有什么共同点呢?仔细看,有三点:

  • 说得出要算的数:总和、平均、个数,或者最大的那几笔。
  • 说得出比的是什么:类别和类别比,月份和月份比,周末和工作日比。
  • 数据里有对应的那一项:记账本的每一笔都记了日期、名称、类别、金额和付款方式,上面这些问题都用得上它们。

反过来,有些问题就没法用这份数据回答。比如「我买的东西值不值」,账本里根本没有记「值不值」,再怎么算也算不出来。问题提得出来,数据却回答不了,这种情况很常见。这时候只有两条路:要么换个问题,要么去找更多的数据。

道理说完了,咱们挑一个最简单的问题来练手:2026 年,每个类别各花了多少钱?

这个问题,第三节就动手来算。在那之前,先花两分钟看看数据分析的全貌:从提出问题到得出结论,一共要走哪几步?

教学 03 / 08

二、数据分析的六步

不管分析的是账单、图书还是天气,要做的事情大体都是下面这六步:

文本
① 提问:想清楚要回答什么
② 获取:把数据拿到手(自己记的、爬虫抓的、别人给的)
③ 清洗:处理缺失、重复、写错的数据
④ 探索:看看数据长什么样,有多少行、每列是什么、有没有怪的值
⑤ 分析:统计、分组、比较,必要时画成图
⑥ 结论:用大白话说清楚发现了什么,以及这个结论靠不靠得住

这门课的章节,基本就是沿着这六步来排的。每一步在哪一章学,可以对照这张表:

步骤在哪一章
获取、探索第 2 章「认识 DataFrame」
探索第 3 章「挑出想要的数据」、第 4 章「用几个数说清一列」
清洗第 5 章「把数据洗干净」
分析第 6 章「分组汇总与透视表」、第 7 章「把几张表拼起来」
分析、画图第 8 章「把数字画成图」
全部六步第 9、10 章两个项目

不过要注意,这六步并不是一条直线,走完一步就再也不回头。比如探索的时候发现数据有问题,就得回到清洗;分析出一个意想不到的结果,可能还要回到提问,换个角度再问一遍。这样来回走好几趟,是很正常的事。

六步里面,最容易被跳过的是第 ⑥ 步的后半句:结论靠不靠得住。为什么这么说呢?因为算出一个数很容易,难的是说清楚这个数能说明什么、不能说明什么,而这恰恰是分析里最有价值的部分。

教学 04 / 08

三、先用学过的办法算一算

回到第一节的问题:2026 年,每个类别各花了多少钱?pandas 还没学,咱们先用已经学过的办法试试看。

记账本存在 ledger_2026.csv 这个文件里。在网页里运行时,网站已经替你放好了这个文件;要是在自己电脑上运行,就得先从 练习靶场 把它下载下来,放在代码文件的旁边。

动手算之前,先看看文件里长什么样。下面的代码只读出文件的前 4 行:

Python· 可在网页运行
with open('ledger_2026.csv', encoding='utf-8') as f:
    for _ in range(4):
        print(f.readline().strip())

输出的结果:

文本
date,item,category,cost,payment
2026-01-01,房租,居住,2500,银行卡
2026-01-01,水电燃气,居住,156,支付宝
2026-01-01,早饭,餐饮,13,支付宝

第一行是表头,说明每一列记的是什么。可以看到,每一笔花销都记了五项:日期、名称、类别、金额和付款方式。

数据的样子清楚了,接下来就可以算了。思路是这样的:一行一行地读,碰到哪个类别,就把这一笔的金额加到这个类别的总数上。读文件用实战 5 学过的 csv 模块,累加用实战 2 学过的字典:

Python· 可在网页运行
import csv

totals = {}
with open('ledger_2026.csv', encoding='utf-8', newline='') as f:
    for row in csv.DictReader(f):
        totals[row['category']] = totals.get(row['category'], 0) + float(row['cost'])

for category, money in sorted(totals.items(), key=lambda item: item[1], reverse=True):
    print(f'{category}:{money:.2f} 元')

输出的结果:

文本
居住:32888.50 元
餐饮:23583.00 元
购物:4992.50 元
娱乐:3178.00 元
交通:1713.00 元
学习:1659.00 元
医疗:1181.50 元

这段代码里,最难懂的大概是最后那个 for 后面的一长串排序。咱们把它拆开来看:

  • totals.items() 把字典变成一对一对的(类别, 金额),比如 ('居住', 32888.5) 。
  • sorted() 负责排序。它不会改动原来的字典,而是排好以后,返回一个新的列表。
  • 那按什么排呢?key=lambda item: item[1] 就是在告诉 sorted() :每一对里取第 2 个值,也就是金额,按金额来排。lambda 是基础课第 6 章讲过的匿名函数,忘了的话可以回去看一眼。
  • reverse=True 的意思是倒过来排,从大到小。

这样一来,花得最多的类别就排在了最前面。看输出,答案出来了:居住花得最多,主要是因为每个月 2500 元的房租;其次是餐饮。

用学过的办法,这个问题总算是算出来了。不过回头看看这段代码,为了得到这几个数,咱们一共做了五件事:打开文件、一行一行地读、把金额从字符串转成数字、用字典累加,最后再排序。

而这还只是最简单的一个问题。要是接着再问一句「每个月、每个类别各花了多少?」,代码还得再长一截。

那么,有没有更省事的办法呢?有,下一节就来试试 pandas。在那之前,先做一道练习,用同样的办法把全年的花销加起来,把这个思路练熟。

练习 1 / 3一年花了多少

用 csv 模块读 ledger_2026.csv ,数一数一共记了几笔,把金额(cost 列)全部加起来。金额读出来是字符串,记得先转成数字。

运行后的输出应该是:

文本
1354 笔,共 69195.50 元
💡 提示(3 条)
  1. DictReader 读出的每一行是字典,金额在 row['cost'],是字符串

  2. total = total + float(row['cost'])

  3. 完整代码:

    Python
    import csv
    
    count = 0
    total = 0
    with open('ledger_2026.csv', encoding='utf-8', newline='') as f:
        for row in csv.DictReader(f):
            count = count + 1
            total = total + float(row['cost'])
    print(f'{count} 笔,共 {total:.2f} 元')
在编辑器里写这题,跑判分、看参考答案去闯关页做这题 →
教学 05 / 08

四、换成 pandas 试试

还是同一个问题:每个类别各花了多少钱?这回换成 pandas 来算:

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

ledger = pd.read_csv('ledger_2026.csv')
print(ledger.groupby('category')['cost'].sum().sort_values(ascending=False))

输出的结果:

文本
category
居住    32888.5
餐饮    23583.0
购物     4992.5
娱乐     3178.0
交通     1713.0
学习     1659.0
医疗     1181.5
Name: cost, dtype: float64

第一次运行时,要多等一会儿:输出区会先显示「正在加载扩展包」,因为 pandas 有几十 MB,得先下载。等它加载完,结果才会出来。

和上一节对比一下,算出来的数一模一样,代码却只剩三行。这三行都做了什么呢?咱们一行一行地看。现在先有个印象就行,后面几章会一样一样地讲透:

  • import pandas as pd :导入 pandas。大家都习惯把它简写成 pd ,后面用起来少打几个字。
  • pd.read_csv('ledger_2026.csv') :读进 csv 文件,得到一张表,pandas 管这种表叫 DataFrame。而且读的时候,它已经自动把金额这一列认成了数字,不用再像上一节那样自己写 float() 。
  • ledger.groupby('category')['cost'].sum() :按类别分组,再把每一组的金额加起来。这一句第 6 章会细讲。
  • .sort_values(ascending=False) :把结果从大到小排序。

在网页里运行,pandas 已经准备好了。要是想在自己电脑上运行,得先安装 pandas:python -m pip install pandas matplotlib 。怎么建虚拟环境、怎么装包,爬虫课第 10 章讲过,没学过的童鞋可以去看看。

看到这里,有的童鞋可能会想:pandas 是不是有什么神奇的地方?其实没有。它之所以好用,是因为数据分析里反复要做的那几件事,比如读文件、挑列、筛选、分组、汇总、排序,它都准备好了现成的写法。学会这些写法,就不用每次都从头写循环,可以把精力花在更要紧的事情上:该问什么问题,算出来的数又该怎么理解。

练习 2 / 3用 pandas 按付款方式汇总

照着第四节的写法,用 pandas 读进 ledger_2026.csv ,按付款方式(payment 列)分组,把金额加起来,从大到小排序后打印。

运行后的输出应该是:

文本
payment
银行卡    34442.5
支付宝    19207.0
微信      15259.5
现金        286.5
Name: cost, dtype: float64
💡 提示(3 条)
  1. 和第四节一样的写法,只是把 'category' 换成 'payment'

  2. ledger.groupby('payment')['cost'].sum().sort_values(ascending=False)

  3. 完整代码:

    Python
    import pandas as pd
    
    ledger = pd.read_csv('ledger_2026.csv')
    print(ledger.groupby('payment')['cost'].sum().sort_values(ascending=False))
在编辑器里写这题,跑判分、看参考答案去闯关页做这题 →
教学 06 / 08

五、常见坑

工具会用了,是不是就能放心地分析了?还不行。下面这几个坑,刚学数据分析的童鞋很容易踩到,而且踩了往往自己还发现不了。

1、没想好问题,就开始算

打开数据,把能算的平均数、总和全都算一遍,最后得到一大堆数,却说不出它们有什么用。所以顺序要反过来:先写下问题,再动手。算出来的每一个数,都应该能回答某个问题。

2、不看原始数据,就下结论

只看汇总的结果,很容易被骗。比如前面算出「居住」花得最多,到底是因为房租,还是因为别的什么?光看一个总数,是看不出来的。这时候回头看一眼原始的那几行,就清楚了:

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

ledger = pd.read_csv('ledger_2026.csv')
home = ledger[ledger['category'] == '居住']
print(home['item'].value_counts())

输出的结果:

文本
item
房租        12
水电燃气    12
话费        12
Name: count, dtype: int64

原来,居住类一共只有三种花销:房租、水电燃气和话费,每个月各一笔。光是 12 笔房租,每笔 2500 元,就占了三万元。这里用到的筛选和计数的写法,第 3、4 章会讲,现在看个大概就行。

3、把平均数当成全部

「平均每笔花了多少」,听上去很能说明问题。可是想一想:一笔 2500 元的房租,就能把一个月的平均数拉高一大截。也就是说,平均数很容易被少数几个特别大的值带偏。那还能看什么呢?第 4 章会专门比较平均数和中位数。

4、忘了数据是怎么来的

这份记账本是编出来的,书店的数据也是编的,拿来练习正合适。可要是拿它们去说「年轻人每年在餐饮上花两万多」,那就完全不对了,因为这只是一个编出来的人的账本,代表不了别人。

所以下结论之前,先问问自己:数据是谁记的?记了多久?有没有漏记?它能代表哪些人?结论只能说到数据撑得住的地方为止。

练习 3 / 3一月份花了多少

问题:2026 年 1 月花了多少钱?用 csv 模块读 ledger_2026.csv ,只累加日期以 2026-01 开头的那些行,同时数一数有几笔。

运行后的输出应该是:

文本
1 月记了 116 笔,共 5289.50 元
💡 提示(3 条)
  1. 日期在 row['date'],是 '2026-01-01' 这样的字符串

  2. 字符串的 startswith('2026-01') 判断开头

  3. 完整代码:

    Python
    import csv
    
    total = 0
    count = 0
    with open('ledger_2026.csv', encoding='utf-8', newline='') as f:
        for row in csv.DictReader(f):
            if row['date'].startswith('2026-01'):
                total = total + float(row['cost'])
                count = count + 1
    print(f'1 月记了 {count} 笔,共 {total:.2f} 元')
在编辑器里写这题,跑判分、看参考答案去闯关页做这题 →
教学 07 / 08

六、自己查一次文档

这一章用到的 read_csv() 、groupby() 这些写法,都是从哪儿来的呢?答案是 pandas 的官方文档。以后碰到不会的写法,最靠得住的也是它。所以这一节,咱们自己查一次。

pandas 的文档只有英文版,而且内容非常多,从头读是读不完的。先认识两个入口就够了:

查 API 参考的时候,要先看清版本,因为不同版本的 pandas,参数可能不一样。那么,网页里用的是哪个版本呢?运行一下就知道了:

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

print(pd.__version__)

输出的结果:

文本
2.2.3

是 2.2 版。所以上面第二个链接,特意选的是 2.2 版的文档。

入口认识了,现在来查一个实际的问题:read_csv() 能不能只读文件的前几行?数据文件很大的时候,先读一小部分看看样子,能省下不少时间。

打开 pandas.read_csv 的说明,会发现参数多达几十个。别从头一个一个地读,用浏览器的查找功能(Windows 上按 Ctrl+F,Mac 上按 ⌘F)搜一下「rows」。很快就能找到一个 nrows ,说明是:Number of rows of file to read. Useful for reading pieces of large files. 意思是:要读多少行,适合用来读大文件的一部分。

查到了,就动手试一试,看看它是不是真的这样:

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

ledger = pd.read_csv('ledger_2026.csv', nrows=3)
print(ledger)

输出的结果:

文本
         date      item category  cost payment
0  2026-01-01      房租     居住  2500  银行卡
1  2026-01-01  水电燃气     居住   156  支付宝
2  2026-01-01      早饭     餐饮    13  支付宝

果然只读了 3 行。

细心的童鞋还会发现一个小地方:金额这回显示成了整数,比如 2500 。可要是读进整个文件,金额会显示成 2500.0 这样带小数点的样子。这是为什么呢?因为前三行的金额碰巧都是整数,pandas 就把这一列认成了整数;而整个文件里有不少带小数的金额,比如 24.5 ,这一列就被认成了小数。数据类型是怎么决定的,下一章会细讲。

另外,在说明里顺着 nrows 往上看,还有一个 usecols ,可以只读需要的那几列。这么多参数,不用全都记住,只要记住一点就够了:read_csv() 的参数很多,想要什么功能,先去文档里搜一搜。

要是英文说明读着费劲,也可以先看例子。pandas 文档里,几乎每个函数的说明下面都有 Examples,代码往往比文字更好懂。

教学 08 / 08

七、小结与回看

这一章,咱们从一个具体的问题出发,先用学过的办法、再用 pandas,把记账本里每个类别的花销算了出来。回头梳理一下,学到了这几件事:

  • 分析从问题开始。好的问题说得出要算什么、比什么,数据里也有对应的那一项。
  • 数据分析有六步:提问、获取、清洗、探索、分析、结论。这六步常常要来回走好几趟。
  • 用 csv 模块加字典能算出答案,而 pandas 用更短的代码就能做同样的事:pd.read_csv() 读进一张表(DataFrame),groupby() 分组,sum() 求和,sort_values() 排序。
  • 常见的坑有四个:没想好问题就开始算;只看汇总,不看原始数据;把平均数当成全部;忘了数据是怎么来的。
  • pandas 的文档是英文的:入门教程按「想做什么」来找,API 参考按函数名来查,查之前先看清版本。比如 read_csv() 的 nrows ,就能只读前几行。

哪里卡住了,就回去看一看:

  • csv 文件的读写:实战 5
  • 字典累加、get() :实战 2「五、钱都花哪儿了?」
  • lambda :第 6 章

这一章只是让 pandas 露了个面。下一章,咱们正式认识 DataFrame:一张表由哪几部分组成,怎么快速看清它有多少行、有哪些列、每列又是什么类型。

读完了?动手练一遍才算真会。

去闯关模式练习 →

学习目录