文章传送门
Python 数据可视化 |
---|
matplotlib之绘制常用图形:折线图、柱状图(条形图)、饼图和直方图 |
matplotlib之设置坐标:添加坐标轴名字、设置坐标范围、设置主次刻度、坐标轴文字旋转并标出坐标值 |
matplotlib之增加图形内容:设置图例、设置中文标题、设置网格效果 |
matplotlib之设置子图:绘制子图、子图共享x轴坐标、调整子图间距、设置图片大小 |
matplotlib之绘制高级图形:散点图、热力图、等值线图、极坐标图 |
matplotlib之绘制三维图形:三维散点图、三维柱状图、三维曲面图 |
目录
- 简述 / 前言
- 1. 通过 add_subplot 方法绘制子图
- 2. 通过 subplot 方法绘制子图
- 3. 两种绘制子图方法的区别
- 4. 子图嵌套
- 5. 子图共享x轴坐标
- 6. 调整子图间距
- 7. 设置图片大小
简述 / 前言
这篇将分享数据可视化最重要也最常用的一个部分——子图,下面将会分享一些常用的方法:绘制子图、子图共享x轴坐标。
1. 通过 add_subplot 方法绘制子图
首先需要新建一个 figure
对象,然后使用 matplotlib.pyplot.figure().add_subplot()
方法绘制子图。
matplotlib.pyplot.figure().add_subplot()
方法有3个参数,第一个参数是把图表划分为几行,第二个参数是把图表划分为几列,第三个参数是当前图形要放在那个区域,比如下面的 add_subplot(2, 2, 1)
就是指图层被划分为2行2列4个区域,该子图在第一个位置创建。
注:图层区域的位置是按照行排序的,即2行2列的区域位置分布如下:
第一个区域(2, 2, 1) 第二个区域(2, 2, 2)
第三个区域(2, 2, 3) 第四个区域(2, 2, 4)
示例:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 10, 0.1)
fig = plt.figure() # 新建figure对象
# 子图1
ax1 = fig.add_subplot(2, 2, 1)
ax1.plot(x, x, label='y=x', color='red')
ax1.legend()
# 子图2
ax2 = fig.add_subplot(2, 2, 3)
ax2.plot(x, 2 * x, label='y=2x', color='blue')
ax2.legend()
# 子图3
ax3 = fig.add_subplot(2, 2, 4)
ax3.plot(x, 4 * x, label='y=4x', color='green')
ax3.legend()
plt.show()
输出:
2. 通过 subplot 方法绘制子图
除了使用 matplotlib.pyplot.figure().add_subplot()
方法绘制子图,还能使用 matplotlib.pyplot
的 subplot()
方法绘制子图。
与 matplotlib.pyplot.figure().add_subplot()
方法一样,matplotlib.pyplot.subplot()
方法也有3个参数,第一个参数是把图表划分为几行,第二个参数是把图表划分为几列,第三个参数是当前图形要放在那个区域,比如下面的 subplot(2, 2, 1)
就是指图层被划分为2行2列4个区域,该子图在第一个位置创建。
注:图层区域的位置是按照行排序的,即2行2列的区域位置分布如下:
第一个区域(2, 2, 1) 第二个区域(2, 2, 2)
第三个区域(2, 2, 3) 第四个区域(2, 2, 4)
示例:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 10, 0.1)
plt.subplot(2, 1, 1) # 第一个子图在2*1的第1个位置
plt.plot(x, x, label='y=x', color='red')
plt.legend()
plt.subplot(2, 2, 3) # 第二个子图在2*2的第3个位置
plt.plot(x, 2 * x, label='y=2x', color='green')
plt.legend()
plt.subplot(2, 2, 4) # 第三个子图在2*2的第4个位置
plt.plot(x, 4 * x, label='y=4x', color='blue')
plt.legend()
plt.show()
输出:
3. 两种绘制子图方法的区别
-
从上面的两个例子可以看出两张输出的图像还是不同的。
matplotlib.pyplot.figure().add_subplot()
方法绘制的子图是完全在一个区域内绘制的;- 而
matplotlib.pyplot.subplot()
方法绘制的子图虽然也是在一个区域内绘制,但是若发现附近区域没有绘制子图,它会占据旁边的子图空间,让图像看起来更自然。
-
假设我们有4个区域,但是只有1、3、4号区域绘制子图:
matplotlib.pyplot.figure().add_subplot()
方法绘制的子图格式如下:第一个子图(2, 2, 1) 子图为空!(2, 2, 2) 第三个子图(2, 2, 3) 第四个子图(2, 2, 4)
- 而
matplotlib.pyplot.subplot()
方法绘制的子图虽然也是在一个区域内绘制,但是若发现附近区域没有绘制子图,它会占据旁边的子图空间,让图像看起来更自然。第一个子图(2, 2, 1&2)【把第二个空子图区域合并了】 第三个子图(2, 2, 3) 第四个子图(2, 2, 4)
4. 子图嵌套
方法就是通过调用 figure
对象的 add_axes
方法创建子图,不管是主图还是嵌套图形都用 add_axes
方法创建子图。
用法:matplotlib.pyplot.figure().add_axes(x, y, len_x, len_y)
,各参数含义如下:
参数 | 含义 |
---|---|
x | 子图x轴距离整张图片在下角多远的位置(水平) |
y | 子图y轴距离整张图片在下角多远的位置(垂直) |
len_x | 子图x轴的长度 |
len_y | 子图y轴的长度 |
以上4个参数的取值范围为:[0, 1],虽然取此范围以外的数字不报错,但是生成的子图将不在图片中。这个其实类似于 HTML 里面的一个相对位置比例,都是相对于整张图片左下角的顶点进行参照的。
值得注意的是,嵌套的子图的参数取值范围应该是:(0, 1)。
不理解的可以自己写代码,调参数画个图就知道了。
示例:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.9, 0.9]) # 大图位置
child_ax = fig.add_axes([0.45, 0.7, 0.2, 0.2]) # 嵌套子图的位置
x = np.arange(0, 10, 0.1)
ax.plot(x, np.sin(x), color='g')
# 子图
childX = np.arange(0, 10, 0.1)
child_ax.plot(childX, np.sin(childX), color='b')
plt.show()
输出:
5. 子图共享x轴坐标
顾名思义,这个就是指好几张垂直摆放的图,它们的 x 轴都是一样的,那么我们只要在最下面那一张图画 x 轴就好了。
-
关键语句:
matplotlib.pyplot.subplots()
-
关键参数:
sharex=True
-
一般用法:
figure, (axClass1, axClass2, ...) = matplotlib.pyplot.subplots(nrows=nrows, ncols=ncols, sharex=True, figsize=(len_x, len_y))
,各参数含义如下:参数 含义 axClass1 第一个子图 axClass2 第二个子图 nrows 行数 nclos 列数 sharex 布尔值(默认为: False
,每个子图都显示x轴的数值),一般改为:True
figsize 子图大小 len_x 子图长度【一般取值范围为:[1, ∞)】 len_y 子图高度【一般取值范围为:[1, ∞)】
示例:
import matplotlib.pyplot as plt
import numpy as np
# 两个子图共享x轴
figure, (axClass1, axClass2) = plt.subplots(2, sharex=True, figsize=(10, 4))
x = np.arange(0, 10, 0.1)
axClass1.plot(x, np.sin(x), color='g')
axClass2.plot(x, np.cos(x), color='b')
axClass1.set_title("$sin(x)$")
axClass2.set_title("$cos(x)$")
plt.show()
输出:
6. 调整子图间距
虽然我们可以设置很多子图,但是一旦子图过多,那么显示图案就会重叠在一起,比如这样:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2024)
data = np.random.rand(100, 2) * 10
x = data[:, 0]
y = data[:, 1]
# 新建figure对象
plt.subplot(131)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("原始数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
# 计算极大值
max_d = np.max(data, axis=0)
# 计算极小值
min_d = np.min(data, axis=0)
# 减去均值,除以标准差
newData = (data - min_d) / (max_d - min_d)
x = newData[:, 0]
y = newData[:, 1]
# 新建figure对象
plt.subplot(132)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("归一化后的数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
# 新建figure对象
plt.subplot(133)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title(f"归一化后的数据\n(放大版)", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.grid()
plt.show()
输出:
那么我们可以通过 matplotlib.pyplot.subplots_adjust(wspace=wspace, hspace=hspace)
来调整子图之间的间距,参数解释如下:
参数 | 含义 |
---|---|
wspace | 子图每一列之间的间隔 |
hspace | 子图每一行之间的间隔 |
改进代码:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2024)
data = np.random.rand(100, 2) * 10
x = data[:, 0]
y = data[:, 1]
# 新建figure对象
plt.subplot(131)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("原始数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
# 计算极大值
max_d = np.max(data, axis=0)
# 计算极小值
min_d = np.min(data, axis=0)
# 减去均值,除以标准差
newData = (data - min_d) / (max_d - min_d)
x = newData[:, 0]
y = newData[:, 1]
# 新建figure对象
plt.subplot(132)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("归一化后的数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
# 新建figure对象
plt.subplot(133)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title(f"归一化后的数据\n(放大版)", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.grid()
# wspace 控制子图列间距, hspace 控制子图横间距
plt.subplots_adjust(wspace=0.5, hspace=0)
plt.show()
输出:
7. 设置图片大小
关键方法:matplotlib.pyplot.figure(figsize=(x, y))
,x和y为画布的长和宽,可自行调整。
特别注意:该语句要在画图前设置,不能画完图后才写这句话(因为这样就会生成2张画布,画好的画在第一张画布)。
示例:
import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(6, 6))
np.random.seed(2024)
data = np.random.rand(100, 2) * 10
x = data[:, 0]
y = data[:, 1]
# 新建figure对象
plt.subplot(231)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("原始数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
# 计算极大值
max_d = np.max(data, axis=0)
# 计算极小值
min_d = np.min(data, axis=0)
# 减去均值,除以标准差
newData = (data - min_d) / (max_d - min_d)
x = newData[:, 0]
y = newData[:, 1]
# 新建figure对象
plt.subplot(232)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title("归一化后的数据", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-5, 20)
plt.ylim(-5, 20)
plt.grid()
# 新建figure对象
plt.subplot(233)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title(f"归一化后的数据\n(放大版)", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.grid()
# 新建figure对象
plt.subplot(234)
plt.scatter(x, y, s=50, alpha=0.7, color='g')
# 设置标题
plt.title(f"归一化后的数据\n(放大版)", fontdict={'fontname': 'FangSong', 'fontsize': 'xx-large', 'fontweight': 'bold'})
plt.xlabel('x轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
# plt.ylabel('y轴', fontdict={'fontname': 'FangSong', 'fontsize': 20})
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.grid()
# wspace 控制子图列间距, hspace 控制子图横间距
plt.subplots_adjust(wspace=0.5, hspace=1)
plt.show()
输出: