【Python数据可视化】matplotlib之设置子图:绘制子图、子图共享x轴坐标、调整子图间距、设置图片大小

文章传送门

Python 数据可视化
matplotlib之绘制常用图形:折线图、柱状图(条形图)、饼图和直方图
matplotlib之设置坐标:添加坐标轴名字、设置坐标范围、设置主次刻度、坐标轴文字旋转并标出坐标值
matplotlib之增加图形内容:设置图例、设置中文标题、设置网格效果
matplotlib之设置子图:绘制子图、子图共享x轴坐标、调整子图间距、设置图片大小
matplotlib之绘制高级图形:散点图、热力图、等值线图、极坐标图
matplotlib之绘制三维图形:三维散点图、三维柱状图、三维曲面图

简述 / 前言

这篇将分享数据可视化最重要也最常用的一个部分——子图,下面将会分享一些常用的方法:绘制子图、子图共享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.pyplotsubplot() 方法绘制子图。

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. 两种绘制子图方法的区别

  1. 从上面的两个例子可以看出两张输出的图像还是不同的。

    • matplotlib.pyplot.figure().add_subplot() 方法绘制的子图是完全在一个区域内绘制的;
    • matplotlib.pyplot.subplot() 方法绘制的子图虽然也是在一个区域内绘制,但是若发现附近区域没有绘制子图,它会占据旁边的子图空间,让图像看起来更自然。
  2. 假设我们有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()

输出:
请添加图片描述

  • 35
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值