把数字画成图
3 道练习题·预计 45 分钟·做对一题解锁下一段
前言
第 6 章里,咱们算出了每个月花了多少,结果是 12 个数排成的一列。可要想知道哪个月最多、是不是越花越多,就得一个一个地比着看,挺费劲的。
有没有更直观的办法呢?有:把这些数画成一张折线图,一眼就看出来了。
所以说,画图不是为了好看,而是为了让数据自己说话。走势、多少、分布、关系,这些在表格里要费劲比较的东西,画到图上,一眼就能看到。而且分析做完以后,要把结论讲给别人听,一张好图也比一页数字管用。
那拿什么来画呢?Python 里画图最常用的工具是 matplotlib 。pandas 的表和列,也能直接调用它来画。和 pandas 一样,它在网页里已经准备好了,代码运行以后,图会显示在输出区里。
学这一章之前,需要先学完 数据分析课第 7 章 。
目录
这一章会学到:
- 一、第一张图——
plt.plot() - 二、用 pandas 画——折线图和柱状图
- 三、看分布——直方图
- 四、看关系——散点图,以及什么问题用什么图
- 五、常见坑
- 六、自己查一次文档——给柱子标上数
- 七、小结与回看
学完这一章,算出来的结果,你都能把它画成一张清楚、不骗人的图。
一、第一张图
matplotlib 到底怎么用呢?咱们先不碰 pandas,就拿两个列表,画一张最简单的图。数据用的是第 6 章算出来的上半年每月花销:
import matplotlib.pyplot as plt
months = [1, 2, 3, 4, 5, 6]
totals = [5289.5, 5272.5, 5418.5, 5799.0, 5712.0, 5485.5]
plt.plot(months, totals)
plt.title('上半年每月花销')
plt.xlabel('月份')
plt.ylabel('金额(元)')
plt.show()运行后,画出来的图是这样的:

这段代码虽然短,用到的却都是画图最基本的几步。咱们一行一行地看:
import matplotlib.pyplot as plt:matplotlib 里管画图的部分叫pyplot,大家都习惯把它简写成plt,就像 pandas 简写成pd一样。plt.plot(横坐标, 纵坐标):两个列表一样长,一个对一个,连成一条线。第一个点是(1, 5289.5),第二个点是(2, 5272.5)……plt.title()、plt.xlabel()、plt.ylabel():分别设置图的标题、横轴的名字和纵轴的名字。plt.show():把图显示出来。
为什么非要写标题和坐标轴的名字呢?因为一张图至少要让人看懂三件事:画的是什么(标题),横着是什么、竖着是什么(坐标轴的名字)。少了哪一个,看图的人都得靠猜。
再说说 plt.show() 。在网页里,它写不写都行,因为运行结束后,画好的图都会显示在输出区。可在自己电脑上就不一样了:它会弹出一个窗口显示这张图,关掉窗口以后,程序才会接着往下走。
还有一点:图上的中文能正常显示,也是因为网页里已经设置好了中文字体。在自己电脑上,还得多写两行,第五节会讲到。
用列表画图,数据得自己一个一个抄进去。可咱们的数据本来就在 pandas 的表里,能不能直接拿来画呢?下一节就来看。
二、用 pandas 画
能不能直接拿 pandas 里的数据来画呢?当然能。数据在 pandas 里的时候,就不用再自己准备列表了。因为 Series 有一个 plot() 方法,它会拿索引当横坐标,拿值当纵坐标,直接画出来。这回把全年的 12 个月都画上:
import pandas as pd
import matplotlib.pyplot as plt
ledger = pd.read_csv('ledger_2026.csv')
ledger['month'] = pd.to_datetime(ledger['date']).dt.month
monthly = ledger.groupby('month')['cost'].sum()
monthly.plot(title='2026 年每月花销')
plt.xlabel('月份')
plt.ylabel('金额(元)')
plt.show()
这段代码里,有三点值得说一说:
monthly的索引是 1 到 12 月,值是每个月的合计,正好一个当横坐标,一个当纵坐标。title可以直接写在plot()的括号里。- 横轴、纵轴的名字,还是用
plt来设置。这是因为 pandas 的plot()背后就是 matplotlib,所以两个可以混着用。
再看图,一眼就能看出来:上半年比较平,8 月冒了一个头,到了年底,11 月、12 月一路往上走。这正是第 6 章从一列数字里费劲找出来的结论。
折线图适合看随时间的变化。那要是想比较几个类别谁多谁少呢?这时候就该用柱状图了。下面用 kind='barh' 画横着的柱子,这样类别的名字也是横着写的,不会挤在一起:
import pandas as pd
import matplotlib.pyplot as plt
ledger = pd.read_csv('ledger_2026.csv')
totals = ledger.groupby('category')['cost'].sum().sort_values()
totals.plot(kind='barh', title='2026 年各类别花销')
plt.xlabel('金额(元)')
plt.ylabel('')
plt.show()
这段代码里,也有三个地方要说一下:
kind决定画什么图:'line'是折线图,也是默认的;'bar'是竖着的柱状图;'barh'是横着的柱状图。- 先用
sort_values()从小到大排好序,横着画的时候,最大的就在最上面,一眼就能看出排名。 plt.ylabel('')是去掉纵轴的名字。因为类别的名字已经写在每根柱子旁边了,再写一个「category」就多余了。
最后还要记住一点:柱状图里,柱子的长短就代表多少,所以柱子一定要从 0 开始画。好在 pandas 和 matplotlib 默认就是这样画的。
先做一道练习:按付款方式把金额加起来,画成一张横向柱状图。
读进记账本,按付款方式把金额加起来,从小到大排序后打印;再把它画成横向柱状图,标题写「各种付款方式的花销」,横轴写「金额(元)」。
运行后的输出应该是:
payment
现金 286.5
微信 15259.5
支付宝 19207.0
银行卡 34442.5
Name: cost, dtype: float64输出下面还要画出一张图。
推荐一个,全网最全最友好的中文 AI 编程指南: coding.stormzhang.ai