绘制简单的线图

让我们使用 Matplotlib 绘制一个简单的折线图,然后对其进行自定义,以创建一个更翔实的数据可视化图表。我们将使用平方数序列 1、4、9、16 和 25 作为图表的数据。

要绘制简单的折线图,只需指定要使用的数字,剩下的就交给 Matplotlib 吧:

mpl_squares.py
import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]

fig, ax = plt.subplots() (1)
ax.plot(squares)

plt.show()

我们首先使用别名 plt 导入 pyplot 模块,这样就不用重复输入 pyplot 了。(pyplot 模块包含大量有助于生成图表和图形的函数。

我们创建一个名为 squares 的列表来保存要绘制的数据。然后,我们遵循 Matplotlib 的另一个惯例,调用 subplots() 函数❶。该函数可以在同一个图中生成一个或多个图。变量 fig 代表整个图,即生成的图的集合。变量 ax 代表图中的单个绘图;这是我们在定义和自定义单个绘图时最常使用的变量。

然后我们使用 plot() 方法,该方法试图以一种有意义的方式绘制所给数据。函数 plt.show() 会打开 Matplotlib 的查看器并显示绘图,如图 15-1 所示。查看器允许您缩放和浏览曲线图,您还可以单击磁盘图标保存任何您喜欢的曲线图。

image 2023 12 04 13 20 12 850
Figure 1. Figure 15-1: One of the simplest plots you can make in Matplotlib

更改标签类型和线粗细

虽然图 15-1 中的曲线图显示数字在增加,但标签字体太小,线条太细,不容易阅读。幸运的是,Matplotlib 允许您调整可视化的每个特征。

我们将使用一些可用的自定义功能来提高图表的可读性。首先,添加标题并标注坐标轴:

mpl_squares.py
import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]

fig, ax = plt.subplots()
ax.plot(squares, linewidth=3) (1)

# Set chart title and label axes.
ax.set_title("Square Numbers", fontsize=24) (2)
ax.set_xlabel("Value", fontsize=14) (3)
ax.set_ylabel("Square of Value", fontsize=14)

# Set size of tick labels.
ax.tick_params(labelsize=14) (4)

plt.show()

linewidth 参数控制着 plot() 生成的线的粗细❶。生成图表后,有许多方法可以在显示前修改图表。set_title() 方法设置图表的总标题❷。在整个代码中反复出现的 fontsize 参数可以控制图表中各种元素的文字大小。

通过 set_xlabel()set_ylabel() 方法可以为每个坐标轴❸ 设置标题,而 tick_params() 方法可以为刻度线❹ 设置样式。在这里,tick_params() 方法将两个坐标轴上刻度线标签的字体大小设置为 14。

如图 15-2 所示,生成的图表更易于阅读。标签字体变大了,折线图也变粗了。通常值得对这些值进行试验,看看哪种值在生成的图表中效果最好。

image 2023 12 04 13 23 46 344
Figure 2. Figure 15-2: The chart is much easier to read now

修正图表

现在我们可以更好地阅读图表了,我们可以看到数据的绘制并不正确。请注意,在图表末尾,4.0 的平方显示为 25!让我们来解决这个问题。

如果给 plot() 一个单一的数字序列,它会假定第一个数据点对应的 x 值为 0,但我们的第一个点对应的 x 值为 1:

mpl_squares.py
import matplotlib.pyplot as plt

input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]

fig, ax = plt.subplots()
ax.plot(input_values, squares, linewidth=3)

# Set chart title and label axes.
--snip--

现在,plot() 不必再假设输出数字是如何生成的了。结果如图 15-3 所示,是正确的。

image 2023 12 04 13 36 09 544
Figure 3. Figure 15-3: The data is now plotted correctly.

在调用 plot() 时,您可以指定多个参数,并在生成图形后使用多种方法自定义图形。在本章中,当我们处理更多有趣的数据集时,我们将继续探索这些自定义方法。

使用内置样式

Matplotlib 提供了大量预定义样式。这些样式包含背景颜色、网格线、线宽、字体、字号等多种默认设置。它们可以让你的可视化效果更吸引人,而不需要太多的自定义。要查看可用样式的完整列表,请在终端会话中运行以下几行:

>>> import matplotlib.pyplot as plt
>>> plt.style.available
['Solarize_Light2', '_classic_test_patch', '_mpl-gallery',
--snip--

要使用这些样式,请在调用 subplots() 之前添加一行代码:

mpl_squares.py
import matplotlib.pyplot as plt

input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]

plt.style.use('seaborn')
fig, ax = plt.subplots()
--snip--

这段代码将生成图 15-4 所示的图形。有多种样式可供选择;请尝试这些样式,找到自己喜欢的样式。

image 2023 12 04 13 44 41 852
Figure 4. Figure 15-4: The built-in seaborn style

使用 scatter() 绘制单个点并设置其样式

有时,根据某些特征来绘制和样式化单个点非常有用。例如,您可以用一种颜色绘制小数值,用另一种颜色绘制大数值。您还可以使用一组样式选项绘制大型数据集,然后使用不同的选项重新绘制,从而突出单个点。

要绘制单个点,可将该点的单个 x 值和 y 值传递给 scatter()

scatter_squares.py
import matplotlib.pyplot as plt

plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(2, 4)

plt.show()

让我们来设计输出样式,使其更有趣。我们将添加标题,标注坐标轴,并确保所有文本足够大,便于阅读:

import matplotlib.pyplot as plt

plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(2, 4, s=200) (1)

# Set chart title and label axes.
ax.set_title("Square Numbers", fontsize=24)
ax.set_xlabel("Value", fontsize=14)
ax.set_ylabel("Square of Value", fontsize=14)

# Set size of tick labels.
ax.tick_params(labelsize=14)

plt.show()

我们调用 scatter() 并使用 s 参数设置绘制图表所用点的❶ 大小。现在运行 scatter_squares.py,应该会在图表中间看到一个点,如图 15-5 所示。

image 2023 12 04 13 52 13 167
Figure 5. Figure 15-5: Plotting a single point

使用 scatter() 绘制一系列点

要绘制一系列点,我们可以将 x 值和 y 值的单独列表传递给 scatter(),就像这样:

import matplotlib.pyplot as plt

x_values = [1, 2, 3, 4, 5]
y_values = [1, 4, 9, 16, 25]

plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=100)

# Set chart title and label axes.
--snip--

x_values 列表包含要平方的数字,y_values 包含每个数字的平方。将这些列表传递给 scatter() 时,Matplotlib 会在绘制每个点时从每个列表中读取一个值。要绘制的点是 (1,1)、(2,4)、(3,9)、(4,16) 和 (5,25);图 15-6 显示了绘制结果。

image 2023 12 04 13 54 17 546
Figure 6. Figure 15-6: A scatter plot with multiple points

自动计算数据

手写列表的效率很低,尤其是当我们有很多点的时候。与其写出每个值,不如用一个循环来完成计算。

下面是 1,000 个点时的情况:

scatter_squares.py
import matplotlib.pyplot as plt

x_values = range(1, 1001)
y_values = [x**2 for x in x_values]

plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=10)

# Set chart title and label axes.
--snip--

# Set the range for each axis.
ax.axis([0, 1100, 0, 1_100_000])

plt.show()

我们从包含数字 1 到 1,000 ❶ 的 x 值范围开始。接下来,通过循环 x 值(for x in x_values)、对每个数字进行平方(x**2)并将结果赋值给 y_values,一个列表理解程序会生成 y 值。然后,我们将输入和输出列表传递给 scatter() ❷。由于数据集较大,我们使用了较小的点尺寸。

在显示曲线图之前,我们使用 axis() 方法指定每个坐标轴的范围❸。axis() 方法需要四个值:x 轴和 y 轴的最小值和最大值。在此,我们将 x 轴的范围设定为 0 至 1,100,y 轴的范围设定为 0 至 1,100,000。图 15-7 显示了结果。

image 2023 12 04 15 39 43 638
Figure 7. Figure 15-7: Python can plot 1,000 points as easily as it plots 5 points.

自定义刻度标签

当坐标轴上的数字足够大时,Matplotlib 会默认使用科学符号来表示刻度标签。这通常是件好事,因为用普通符号表示的较大数字会在可视化中占据大量不必要的空间。

图表的几乎所有元素都可以自定义,因此如果您喜欢,可以告诉 Matplotlib 继续使用普通符号:

--snip--
# Set the range for each axis.
ax.axis([0, 1100, 0, 1_100_000])
ax.ticklabel_format(style='plain')

plt.show()

使用 ticklabel_format() 方法,可以覆盖任何绘图的默认刻度线标签样式。

定义自定义颜色

要更改点的颜色,可将参数 color 传递给 scatter(),并在引号中加上要使用的颜色名称,如图所示:

ax.scatter(x_values, y_values, color='red', s=10)

您还可以使用 RGB 颜色模型定义自定义颜色。要定义颜色,只需在 color 参数中传递一个包含三个浮点数值的元组(红、绿、蓝各一个,依次递增),数值在 0 和 1 之间。 例如,下面一行创建了一个浅绿色点的绘图:

ax.scatter(x_values, y_values, color=(0, 0.8, 0), s=10)

数值越接近 0 颜色越深,数值越接近 1 颜色越浅。

使用色彩图

色彩图是一个渐变色序列,从起始色到终止色。在可视化中,色谱图用于强调数据中的模式。例如,你可以将低值设为浅色,将高值设为深色。使用色标图可以确保可视化中的所有点都能沿着精心设计的色标平滑、准确地变化。

pyplot 模块包含一组内置的颜色图。要使用这些颜色图,需要指定 pyplot 如何为数据集中的每个点分配颜色。下面是如何根据 y 值为每个点分配颜色:

scatter_squares.py
--snip--
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues,s=10)

# Set chart title and label axes.
--snip--

c 参数与 color 类似,但它用于将一系列数值与颜色映射关联起来。我们将 y 值列表传递给 c,然后用 cmap 参数告诉 pyplot 使用哪个颜色映射。这段代码将 y 值较低的点用浅蓝色着色,将 y 值较高的点用深蓝色着色。图 15-8 显示了绘制的结果。

你可以访问 https://matplotlib.org,查看 pyplot 中所有可用的色图。转到 "教程",向下滚动到 "颜色",然后单击 "在 Matplotlib 中选择颜色图"。

image 2023 12 04 15 45 25 939
Figure 8. Figure 15-8: A plot using the Blues colormap

自动保存您的绘图

如果您想将绘图保存到文件中,而不是在 Matplotlib 查看器中显示,可以使用 plt.savefig() 代替 plt.show()

plt.savefig('squares_plot.png', bbox_inches='tight')

第一个参数是绘图图像的文件名,将保存在与 scatter_squares.py 相同的目录下。第二个参数是修剪图中多余的空白。如果希望在绘图周围保留额外的空白,可以省略此参数。您也可以使用路径对象调用 savefig(),然后将输出文件写入系统中的任意位置。

亲身体验

15-1. 立方体 上升到三次幂的数就是立方数。绘制前五个立方数,然后绘制前 5,000 个立方数。

15-2. 彩色立方体: 在立方体图上绘制颜色图。