📊 第5章 可视化数据分析图表
📄 一句话概括

Matplotlib 的套路就三步:造画布、画、存(或显示)。 fig, ax = plt.subplots() 一行拿到「纸」和「图」,后面所有操作都在 ax 上。 不写 plt.show() 也能存图。没有显示器的机器上,show 什么都不干。

📝 本章和前面几章的关系

上一篇讲选什么图,这一篇讲怎么把图画出来。工具是 Matplotlib。 本机 matplotlib 3.11.1,后端用 Agg(没有显示器),所有图存成 PNG。

一、三步走

第一步 fig, ax = plt.subplots(),第二步 ax.plot(x, y),第三步 fig.savefig()。 三行代码,一张折线图就出来了,存成 PNG 26524 字节。 fig 是纸,ax 是纸上的图。后面调标题、调刻度,全在 ax 上做。

要调整张纸(尺寸、边距、一张纸贴几块图),才动 fig。

二、x 不给会怎样

ax.plot([88, 92, 75, 85, 90]) 只给一组数,x 自动取 0 到 4。 所以第一个点横坐标是 0,不是 1。这一点在标刻度的时候会咬人。 想从 1 开始就自己给 x。ax.plot(range(1, 6), y),一步到位。

三、两种写法:面向对象与 pyplot

写法 长什么样 什么时候用
面向对象 ax.plot / ax.set_title 多子图、要精细控制
pyplot plt.plot / plt.title 单张图、快速看

两种都能出图,结果一样。区别是 plt.plot 作用在「最后一个」axes 上。 一张纸上有四块图时,plt.plot 只画到最后那块,前面三块不动。 多子图一律用面向对象写法。单张图用哪种都行,但别在同一个脚本里混着用。

四、看图的时候先看什么

先看形状:是往上走、往下走,还是平的?有没有突跳、有没有缺口? 再看坐标:纵轴从几开始?刻度间隔多少?单位是什么? 顺序不能反。先看坐标容易被数字带走,反而看不见整体形状。

纵轴不从 0 开始时,一点小起伏会被放大几十倍,看起来像暴跌。

五、动手 Demo:Matplotlib 初体验:第一张图

画一条五个点的折线,标上标题和轴标签,存成 PNG 并打出字节数。 再用 pyplot 写法画一张一样的,对比两种写法。

import os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

fig, ax = plt.subplots(figsize=(6, 4))
ax.plot([1, 2, 3, 4, 5], [88, 92, 75, 85, 90], marker="o")
ax.set_title("语文成绩折线")
ax.set_xlabel("序号")
ax.set_ylabel("分数")
fig.savefig("first.png")
print("字节 %d" % os.path.getsize("first.png"))

plt.figure()
plt.plot([1, 2, 3], [3, 1, 2])
plt.savefig("pyplot.png")
print("pyplot 版 %d 字节" % os.path.getsize("pyplot.png"))

实跑输出:

--------------------------------------------------------------------
Matplotlib 初体验:第一张图
--------------------------------------------------------------------

  ① 三步:造画布、画、存
  --------------------------------------------------------------------
  第一张图存成 26524 字节。
  fig, ax = plt.subplots() 一行拿到「纸」和「图」,后面所有操作都在 ax 上做。
  plot 只给一组 y 值时,x 自动用 0 到 n-1。所以第一个点是 0 号,不是 1 号。
  ! 不写 plt.show() 也能存图。没有显示器的机器上,show 什么都不干。

  ② 两种写法:面向对象与 pyplot
  --------------------------------------------------------------------
  上面是面向对象(ax.plot),下面是 pyplot(plt.plot)。两种都能出图。
  plt.plot 作用在「最后一个」axes 上。一张纸上有好几块图时,它只认最后那块。
  ! 多子图一律用面向对象写法。单张图用哪种都行,但别混着用。

  ③ 看图的时候看什么
  --------------------------------------------------------------------
  这张图三个点:(0,3)、(1,1)、(2,2)。中间的谷底在 x=1。
  先看形状,再看坐标。形状对了再看具体数值,否则容易被刻度误导。
  ! 纵轴不从 0 开始时,起伏会被放大几十倍——看起来「暴跌」,其实只差一点点。

matplotlib.use('Agg') 要在 import pyplot 之前调,顺序反了不生效。 font.sans-serif 设成 SimHei 才能写中文。不设的话中文全是方块。

30 秒实验

  1. 把 marker 去掉,看折线变成什么样子。
  2. 把 savefig 的文件名改成 .pdf,看字节数怎么变。
  3. 想一想:如果不写 figsize,图会有多大?改一下量一量。

常见误区

  1. 以为必须 plt.show():没有显示器的机器上它什么都不干,存图才管用。
  2. 用 Agg 之前先 import pyplot:后端设不上,有些环境会直接报错。
  3. 忘了设中文字体:标题里的中文全变成方块。
  4. x 不给就以为从 1 开始:默认从 0 起,标刻度时会错一位。
自测三问(点开对答案) 1. Matplotlib 的三步是哪三步? —— 造画布(subplots)、画(plot)、存(savefig)。显示是第四步,但在服务器上可以省。 2. fig 和 ax 各是什么? —— fig 是整张纸,管尺寸和布局;ax 是纸上的那块图,管数据、标题、刻度。 3. 为什么要设 font.sans-serif? —— Matplotlib 默认字体不带中文,不换字体所有中文都渲染成方块。

第一张图出来了。下一篇讲画布本身:尺寸、清晰度、一条线里放多组数据。

相关笔记