数据分析在做什么
完整讲解 · 8 段教学·配 3 道练习题·预计 40 分钟
本页是本章的通读版,可直接读完全部讲解。想动手写代码、跑判分,去 闯关模式。
前言
各位童鞋学到这里,手里其实已经攒了不少数据:实战 6 的记账本,记下了每一笔花销;学过爬虫课的童鞋,还从书店网站上抓下了一整个书店的图书。
数据是有了,可光把它们存着,并没有什么用。咱们真正想知道的是:这些数据能告诉我们什么?
比如,一年下来,钱主要花在了哪儿?哪个月花得最多?书店里,贵的书评分会不会更高?这些问题的答案,其实就藏在数据里。把答案找出来的过程,就叫数据分析。
那么,拿什么来做数据分析呢?这门课一共 10 章,用的是 Python 里做数据分析最常用的两个工具:
- pandas:把数据装进一张「表」里。筛选、统计、分组、合并,几行代码就能搞定。
- matplotlib:把数字画成图,让人一眼就看出趋势和差别。
练习用的数据有两份,都是编出来的:一份是 2026 年一整年的记账本,另一份是两点书店的图书和读者评分。前 8 章一样一样地学工具,最后两章是两个完整的分析项目,每个项目都要写出一份分析结论。
有一件事要先说在前面:pandas 和 matplotlib 加起来有几十 MB,第一次运行代码时,网页要先把它们下载下来。这时候输出区会显示下载进度,请耐心等一会儿。下载过一次以后,浏览器就记住了,下次不用再等这么久。
最后还想说一句。学数据分析,最怕的其实不是不会写代码,而是算出一个数,就急着下结论。所以这门课在教每一样工具的同时,还会一直追问两个问题:这个数说明了什么?它会不会骗了你?
学这一章之前,需要先学完基础课的第 0~9 章和实战 1~6,尤其是 实战 5 里的 csv 文件读写,这一章马上就会用到。爬虫课没学过也不要紧:最后一个项目要用到爬虫抓下的数据,网站已经提前替你准备好了。
目录
这一章会学到:
- 一、从一个问题开始——什么样的问题能用数据回答
- 二、数据分析的六步——提问、获取、清洗、探索、分析、结论
- 三、先用学过的办法算一算——csv 模块加字典
- 四、换成 pandas 试试——同样的事,三行代码
- 五、常见坑
- 六、自己查一次文档——pandas 的说明书在哪儿
- 七、小结与回看
学完这一章,你会知道数据分析要做哪几件事,并用 pandas 读进第一份数据、算出第一个结果。
一、从一个问题开始
拿到一份数据,很多童鞋的第一反应是:赶紧写代码,算点什么出来。其实先别急,第一件事应该是想清楚:我到底想知道什么?
比如手里有一年的记账本,你对自己说:「分析一下我的账。」这算不算一个问题呢?其实不算。因为它太笼统了,根本不知道该从哪儿下手:是算一共花了多少?还是看哪一类花得最多?
好的问题,要具体到能用数据回答。对比一下就清楚了:
| 笼统的 | 具体的 |
|---|---|
| 我花钱多不多? | 2026 年一共花了多少?平均每个月多少? |
| 钱都去哪儿了? | 每个类别各花了多少,哪个类别最多? |
| 我是不是乱花钱? | 单笔超过 200 元的花销有几笔,都是什么? |
| 周末是不是花得多? | 周末平均每天花多少,工作日平均每天花多少? |
那么,右边这些具体的问题,有什么共同点呢?仔细看,有三点:
- 说得出要算的数:总和、平均、个数,或者最大的那几笔。
- 说得出比的是什么:类别和类别比,月份和月份比,周末和工作日比。
- 数据里有对应的那一项:记账本的每一笔都记了日期、名称、类别、金额和付款方式,上面这些问题都用得上它们。
反过来,有些问题就没法用这份数据回答。比如「我买的东西值不值」,账本里根本没有记「值不值」,再怎么算也算不出来。问题提得出来,数据却回答不了,这种情况很常见。这时候只有两条路:要么换个问题,要么去找更多的数据。
道理说完了,咱们挑一个最简单的问题来练手:2026 年,每个类别各花了多少钱?
这个问题,第三节就动手来算。在那之前,先花两分钟看看数据分析的全貌:从提出问题到得出结论,一共要走哪几步?
二、数据分析的六步
不管分析的是账单、图书还是天气,要做的事情大体都是下面这六步:
① 提问:想清楚要回答什么
② 获取:把数据拿到手(自己记的、爬虫抓的、别人给的)
③ 清洗:处理缺失、重复、写错的数据
④ 探索:看看数据长什么样,有多少行、每列是什么、有没有怪的值
⑤ 分析:统计、分组、比较,必要时画成图
⑥ 结论:用大白话说清楚发现了什么,以及这个结论靠不靠得住这门课的章节,基本就是沿着这六步来排的。每一步在哪一章学,可以对照这张表:
| 步骤 | 在哪一章 |
|---|---|
| 获取、探索 | 第 2 章「认识 DataFrame」 |
| 探索 | 第 3 章「挑出想要的数据」、第 4 章「用几个数说清一列」 |
| 清洗 | 第 5 章「把数据洗干净」 |
| 分析 | 第 6 章「分组汇总与透视表」、第 7 章「把几张表拼起来」 |
| 分析、画图 | 第 8 章「把数字画成图」 |
| 全部六步 | 第 9、10 章两个项目 |
不过要注意,这六步并不是一条直线,走完一步就再也不回头。比如探索的时候发现数据有问题,就得回到清洗;分析出一个意想不到的结果,可能还要回到提问,换个角度再问一遍。这样来回走好几趟,是很正常的事。
六步里面,最容易被跳过的是第 ⑥ 步的后半句:结论靠不靠得住。为什么这么说呢?因为算出一个数很容易,难的是说清楚这个数能说明什么、不能说明什么,而这恰恰是分析里最有价值的部分。
三、先用学过的办法算一算
回到第一节的问题:2026 年,每个类别各花了多少钱?pandas 还没学,咱们先用已经学过的办法试试看。
记账本存在 ledger_2026.csv 这个文件里。在网页里运行时,网站已经替你放好了这个文件;要是在自己电脑上运行,就得先从 练习靶场 把它下载下来,放在代码文件的旁边。
动手算之前,先看看文件里长什么样。下面的代码只读出文件的前 4 行:
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 学过的字典:
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。在那之前,先做一道练习,用同样的办法把全年的花销加起来,把这个思路练熟。
用 csv 模块读 ledger_2026.csv ,数一数一共记了几笔,把金额(cost 列)全部加起来。金额读出来是字符串,记得先转成数字。
运行后的输出应该是:
1354 笔,共 69195.50 元💡 提示(3 条)
DictReader 读出的每一行是字典,金额在 row['cost'],是字符串
total = total + float(row['cost'])
完整代码:
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} 元')
四、换成 pandas 试试
还是同一个问题:每个类别各花了多少钱?这回换成 pandas 来算:
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 是不是有什么神奇的地方?其实没有。它之所以好用,是因为数据分析里反复要做的那几件事,比如读文件、挑列、筛选、分组、汇总、排序,它都准备好了现成的写法。学会这些写法,就不用每次都从头写循环,可以把精力花在更要紧的事情上:该问什么问题,算出来的数又该怎么理解。
照着第四节的写法,用 pandas 读进 ledger_2026.csv ,按付款方式(payment 列)分组,把金额加起来,从大到小排序后打印。
运行后的输出应该是:
payment
银行卡 34442.5
支付宝 19207.0
微信 15259.5
现金 286.5
Name: cost, dtype: float64💡 提示(3 条)
和第四节一样的写法,只是把 'category' 换成 'payment'
ledger.groupby('payment')['cost'].sum().sort_values(ascending=False)
完整代码:
import pandas as pd ledger = pd.read_csv('ledger_2026.csv') print(ledger.groupby('payment')['cost'].sum().sort_values(ascending=False))
五、常见坑
工具会用了,是不是就能放心地分析了?还不行。下面这几个坑,刚学数据分析的童鞋很容易踩到,而且踩了往往自己还发现不了。
1、没想好问题,就开始算
打开数据,把能算的平均数、总和全都算一遍,最后得到一大堆数,却说不出它们有什么用。所以顺序要反过来:先写下问题,再动手。算出来的每一个数,都应该能回答某个问题。
2、不看原始数据,就下结论
只看汇总的结果,很容易被骗。比如前面算出「居住」花得最多,到底是因为房租,还是因为别的什么?光看一个总数,是看不出来的。这时候回头看一眼原始的那几行,就清楚了:
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、忘了数据是怎么来的
这份记账本是编出来的,书店的数据也是编的,拿来练习正合适。可要是拿它们去说「年轻人每年在餐饮上花两万多」,那就完全不对了,因为这只是一个编出来的人的账本,代表不了别人。
所以下结论之前,先问问自己:数据是谁记的?记了多久?有没有漏记?它能代表哪些人?结论只能说到数据撑得住的地方为止。
问题:2026 年 1 月花了多少钱?用 csv 模块读 ledger_2026.csv ,只累加日期以 2026-01 开头的那些行,同时数一数有几笔。
运行后的输出应该是:
1 月记了 116 笔,共 5289.50 元💡 提示(3 条)
日期在 row['date'],是 '2026-01-01' 这样的字符串
字符串的 startswith('2026-01') 判断开头
完整代码:
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} 元')
六、自己查一次文档
这一章用到的 read_csv() 、groupby() 这些写法,都是从哪儿来的呢?答案是 pandas 的官方文档。以后碰到不会的写法,最靠得住的也是它。所以这一节,咱们自己查一次。
pandas 的文档只有英文版,而且内容非常多,从头读是读不完的。先认识两个入口就够了:
- 入门教程(Getting started tutorials) :一组短小的教程,按「我想做什么」来组织,比如「怎么读写表格数据」「怎么选取一部分数据」。
- API 参考(API reference) :每个函数的完整说明。用到某个函数,想知道它有哪些参数时,就来这里查。
查 API 参考的时候,要先看清版本,因为不同版本的 pandas,参数可能不一样。那么,网页里用的是哪个版本呢?运行一下就知道了:
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. 意思是:要读多少行,适合用来读大文件的一部分。
查到了,就动手试一试,看看它是不是真的这样:
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,代码往往比文字更好懂。
七、小结与回看
这一章,咱们从一个具体的问题出发,先用学过的办法、再用 pandas,把记账本里每个类别的花销算了出来。回头梳理一下,学到了这几件事:
- 分析从问题开始。好的问题说得出要算什么、比什么,数据里也有对应的那一项。
- 数据分析有六步:提问、获取、清洗、探索、分析、结论。这六步常常要来回走好几趟。
- 用 csv 模块加字典能算出答案,而 pandas 用更短的代码就能做同样的事:
pd.read_csv()读进一张表(DataFrame),groupby()分组,sum()求和,sort_values()排序。 - 常见的坑有四个:没想好问题就开始算;只看汇总,不看原始数据;把平均数当成全部;忘了数据是怎么来的。
- pandas 的文档是英文的:入门教程按「想做什么」来找,API 参考按函数名来查,查之前先看清版本。比如
read_csv()的nrows,就能只读前几行。
哪里卡住了,就回去看一看:
- csv 文件的读写:实战 5
- 字典累加、
get():实战 2「五、钱都花哪儿了?」 lambda:第 6 章
这一章只是让 pandas 露了个面。下一章,咱们正式认识 DataFrame:一张表由哪几部分组成,怎么快速看清它有多少行、有哪些列、每列又是什么类型。
读完了?动手练一遍才算真会。
去闯关模式练习 →