在上一篇文章中,我们处理了使用 Pandas 和 Matplotlib 可视化数据的练习问题。
这次我们将了解如何使用 Matplotlib 同时绘制多个图形的子图。
1. Subplots
子图会接收绘制图的空间坐标,并返回整体图形和每个图形的坐标轴。
fig, axis = plt.subplots(2,2, constrained_layout=True)
axis查看axis 中的内容,可以发现每个坐标轴以 2 行 2 列的形式存在。
因为都是对象,所以可以单独处理。

在 Jupyter Notebook 中图形会直接绘制出来。
由于尚未输入任何内容,显示出四个空的图形。

让我们逐个填充图形。绘制了不同 y 值但相同 x 值的图形。
axis 的形式如下注释,因此可以如坐标般访问。
x = [1,2,3,4,5]
y1 = [1,2,3,4,5]
y2 = [1,3,5,7,9]
y3 = [1,4,9,16,26]
y4 = [1,8,27,64,125]
# axis 内部从左上角开始,向右
# [[第一个, 第二个],[第三个, 第四个]] 是图形对象。
axis[0][0].plot(x,y1)
axis[0][1].plot(x,y2)
axis[1][0].plot(x,y3)
axis[1][1].plot(x,y4)
fig对比以上代码和下图,可以看到如何匹配。

可以访问每个图形对象进行详细修改。
在以前用plt 的函数前加 set_即可。
axis[0][0].plot(x,y1, label="y=x")
axis[0][0].set_title("第一个图形")
axis[0][0].set_xlabel("这是 x 轴")
axis[0][0].set_ylabel("这是 y 轴")
axis[0][0].set_xticks(x)
axis[0][0].set_yticks(y1)
axis[0][0].legend()可以看到第一个图形已正确修改。

让我们用同样的方法修改其他图形。
由于硬编码不优雅,尝试通过嵌套 for 循环访问每个对象后进行修改。
x = [1,2,3,4,5]
y1 = [1,2,3,4,5]
y2 = [1,3,5,7,9]
y3 = [1,4,9,16,26]
y4 = [1,8,27,64,125]
# 创建包含 y 值和图例的列表
# 使用 nums 使其可以循环添加 4 个值
ys = [y1,y2,y3,y4]
legends = ["y=x", "y=2x-1", "y=x^2", "y=x^3"]
nums = 0
# 嵌套循环遍历 (0,0), (0,1), (1,0), (1,1)
for i in range(2):
for j in range(2):
# 添加 x 值和 ys 中 nums 的值
axis[i][j].plot(x,ys[nums], label=legends[nums])
axis[i][j].set_title(f"第 {nums+1} 个图形")
axis[i][j].set_xlabel("这是 x 轴")
axis[i][j].set_ylabel("这是 y 轴")
axis[i][j].set_xticks(x)
axis[i][j].set_yticks(ys[nums])
axis[i][j].legend()
nums += 1
fig虽然最后一个图形的轴有些不满意,但都已正确修改。

2. 应用示例
上次,我们绘制了按年统计的犯罪发生次数和拘捕次数的子图。
显然,首先使用 pandas 读取值。
import pandas as pd
# 调用模块并设置韩文字体
import matplotlib.pyplot as plt
import matplotlib
# MacOS 字体设置
# matplotlib.rcParams["font.family"] = "AppleGothic"
# Windows 字体设置
matplotlib.rcParams["font.family"] = "Malgun Gothic"
# 字体大小设置
matplotlib.rcParams["font.size"] = 13
# 解决负号输出问题
plt.rcParams['axes.unicode_minus'] = False
crime = pd.read_excel("./crime_statistics.xlsx")
crime.head(3)

查看了数据列中包含“黑客”的所有项。
由于总共有4个图形,只选择了4个列。
接着将 x 指定为年份,y1 为发生次数,y2 为拘捕次数。
cols = [i for i in crime.columns if "黑客" in i]
cols = cols[:4]
x = crime.iloc[:,0].unique()
y1 = crime.loc[crime.구분=="发生次数",cols[0]]
y2 = crime.loc[crime.구분=="拘捕次数",cols[0]]
此强绘制了第一个图形。
fig, axis = plt.subplots(2,2, constrained_layout=True)
axis[0][0].plot(x,y1,label="发生次数")
axis[0][0].plot(x,y2,label="拘捕次数")
axis[0][0].legend()
axis[0][0].set_title(cols[0])
axis[0][0].legend()图形绘制得很好。虽然不太满意图例的位置和文字大小,但可先绘制后修改。
现在构建一个嵌套 for 循环来绘制整体图形。

将整段代码放入 for 循环中并更改必要的部分。
首先要将坐标轴部分改为 axis[i][j],一一更改既困难又不美观。
按下 Alt + Shift 并拖动鼠标激活多光标。
删除 [0][0] 部分并更改为 [i][j]。


修改完所有代码后,如下所示。
执行后可以很好地绘制出图形。
fig, axis = plt.subplots(2,2, constrained_layout=True)
col_nums = 0
for i in range(2):
for j in range(2):
y1 = crime.loc[crime.구분=="发生次数",cols[col_nums]]
y2 = crime.loc[crime.구분=="拘捕次数",cols[col_nums]]
axis[i][j].plot(x,y1,label="发生次数")
axis[i][j].plot(x,y2,"--",label="拘捕次数")
axis[i][j].legend()
axis[i][j].set_title(cols[col_nums])
axis[i][j].legend()
col_nums += 1如果对图例不满意,可以通过fontsize 参数减小文字大小,或使用 bbox_to_achor 参数更改图例位置。

代码现在完成。如果想查看其他数据,只需更改cols 中的列名。
这次换成“赌博”。
然后执行其他代码将自动绘制关于赌博的图形。


这次让我们绘制关于网络金融犯罪的图形。

图形显示出自 2016 年至 2018 年,犯罪模式发生了重大变化。

3. 结语
今天我们学习了如何使用 matplotlib 的子图。
这里仅使用简单的 plot 绘制图形,但可以应用各种图形,如条形、水平条形和小提琴图。
下次我们将使用 numpy 模块绘制线性回归分析图形。
댓글을 불러오는 중...