两次 plot 落在同一个 ax 上就是两条线,label 一给图例才有内容。 一条 plot 传二维数组时,按列画线:列数就是线条数。 figsize 管多大,dpi 管多细。尺寸翻倍字节只涨三成多,因为文字开销是固定的。
上一篇只画了一条线。这一篇讲多组数据怎么画,还有画布尺寸怎么定。 材料是六个月的销售额:128000、116000、143000、151000、138000、162000。
一、一个 ax 上画多条线
连续两次 ax.plot(...),两条线就落在同一张图上。
每次 plot 给一个 label,最后 ax.legend() 统一调出图例。
不写 label,图例就是空的。这是「图例没出来」最常见的原因。
线多了要分配颜色,可以显式给 color,也可以让 Matplotlib 自动轮换。 自动轮换在超过五条线时会开始重复颜色,这时候得自己定。
二、一条 plot 传二维数据
传一个 6 行 2 列的数组,它按列画两条线,和两次 plot 效果一样。 6 行 2 列画两条,2 行 6 列画六条——列数才是线条数。 数据本来就在 ndarray 里时这样写省事,但行列关系容易搞混。
新手最常犯的错是把表转置忘了,画出一条横跨全屏的怪线。
三、画布尺寸:figsize
| figsize | 存成多少字节 | 面积 |
|---|---|---|
| (4, 3) | 12707 | 12 |
| (6, 4) | 17293 | 24 |
| (8, 6) | 23720 | 48 |
面积翻倍,字节只涨三成多——因为文字和坐标轴这些固定开销不随面积线性涨。 figsize 的单位是英寸。默认 (6.4, 4.8),差不多是一张 A4 纸的三分之一。 屏幕上看,宽 8 到 10 英寸已经够大;打印的话按实际版面尺寸给。
四、清晰度:dpi
dpi 是每英寸多少个点。默认 100,印刷标准是 300。 同样一张 6 乘 4 的图,dpi=100 是 17293 字节,dpi=300 是 63367 字节。 尺寸和 dpi 是两件事。尺寸管「多大」,dpi 管「多细」。
两个都调,文件会暴涨。屏幕上看的图,dpi 保持 100 就好。
五、动手 Demo:plot 函数与画布
先画同一张图上的两条线,再用二维数组合成地画一次。 最后用三种 figsize 存图,比字节数。
import os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
M = [128000, 116000, 143000, 151000, 138000, 162000]
fig, ax = plt.subplots()
ax.plot(range(6), M, label="今年", marker="o")
ax.plot(range(6), [m * 1.1 for m in M], label="去年", marker="s")
ax.legend()
fig.savefig("two_lines.png")
print("两条线 %d 字节" % os.path.getsize("two_lines.png"))
for w, h in [(4, 3), (6, 4), (8, 6)]:
f, a = plt.subplots(figsize=(w, h))
a.plot(range(6), M)
f.savefig("size_%dx%d.png" % (w, h))
print("figsize (%d,%d) -> %d 字节"
% (w, h, os.path.getsize("size_%dx%d.png" % (w, h))))
plt.close(f)
实跑输出:
--------------------------------------------------------------------
plot 函数与画布
--------------------------------------------------------------------
① 一条 plot 画多条线
--------------------------------------------------------------------
两次 plot 落在同一个 ax 上,就是两条线。
上半年最低 116000、最高 162000;去年同期的线整体在上面。
! 图例要写在 plot 里(label=),不写 label 图例是空的。
② 一条 plot 传二维数据
--------------------------------------------------------------------
传一个 6 行 2 列的数组,它按列画两条线——和两次 plot 效果一样。
数据在 ndarray 里时这样写省事,但列和线的对应关系容易搞混。
! 列数就是线条数。6 行 2 列画两条,2 行 6 列画六条。
③ 画布大小与清晰度
--------------------------------------------------------------------
figsize=(4, 3) 存成 12707 字节。
figsize=(6, 4) 存成 17293 字节。
figsize=(8, 6) 存成 23720 字节。
figsize 单位是英寸,默认 (6.4, 4.8)。面积翻倍,字节只涨三成多——文字和坐标轴的开销是固定的。
dpi 管清晰度,默认 100。要打印就设 300,屏幕上看 100 够了。
! 尺寸和 dpi 是两件事。尺寸管「多大」,dpi 管「多细」。两个都调,文件会暴涨。
循环里每张图都要 plt.close(f),不然画布会一直攒着,几十张之后内存爆掉。
plt.close() 是批量画图必写的一行。单张图不写也行,循环里不写会出事。
30 秒实验
- 把二维数组转置一下再 plot,看线条数变成几条。
- 给两条线显式指定 color='red' 和 color='blue',看能不能覆盖默认配色。
- 想一想:为什么 figsize 从 (4,3) 到 (8,6) 面积翻四倍,字节只涨不到一倍?
常见误区
- 忘了 label 就调 legend:图例框出来是空的。
- 二维数组行列搞反:线条数不对,画出一堆横线。
- 循环里不 close 画布:内存一路涨,跑到几十张就卡死。
- 以为 figsize 是像素:它是英寸,乘上 dpi 才是像素。
自测三问(点开对答案)
1. 两条线怎么画在同一张图上? —— 两次调用同一个 ax 的 plot,各自给 label,最后 ax.legend()。 2. 一条 plot 传 6 行 2 列的数组会画几条线? —— 两条。按列画,列数就是线条数。 3. figsize 和 dpi 各管什么? —— figsize 管图的物理尺寸(英寸),dpi 管每英寸多少点,两者相乘才是像素尺寸。图能画了,但坐标轴上的字可能对不上。下一篇专门收拾刻度。
- ☐ (本篇完,下一篇 5.4 坐标轴与刻度)