问题背景
我在最初用plt.subplots画多个子图时,都是纵向排列的,如下所示:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg') # 为了避免matplotlib版本过高而报错,报错提示为:AttributeError: module 'backend_interagg' has no attribute 'FigureCanvas'
fig, axs = plt.subplots(4, 1, figsize=(14, 8)) # 绘制几个纵向排列子图
axs[0].plot(data_2.loc[:, 'Elapsed time (s)'], data_2.loc[:, 'speed_raw (公里/小时)']) # 我用的是DataFrame中的数据
# axs[0].set_title('Subplot1')
axs[0].set_xlabel('time(s)')
axs[0].set_ylabel('Speed(km/h)')
axs[1].plot(data_2.loc[:, 'Elapsed time (s)'], data_2.loc[:, 'acceleration(m/s^2)'])
axs[1].set_xlabel('time(s)')
axs[1].set_ylabel('acceleration(m/s^2)')
axs[2].plot(data_2.loc[:, 'Elapsed time (s)'], data_2.loc[:, 'gradient'])
axs[2].set_xlabel('time(s)')
axs[2].set_ylabel('gradient')
axs[3].plot(data_2.loc[:, 'Elapsed time (s)'], data_2.loc[:, '高度 (米)'])
axs[3].set_xlabel('time(s)')
axs[3].set_ylabel('height(m)')
plt.subplots_adjust(hspace=0.8) # 调整子图之间的间距
plt.show() # 在关闭图像后,才会继续执行后续的代码
显示图像为:
并没有什么问题,一纵列四个,分别用axs[0]、axs[1]、axs[2]、axs[3]所指定,其中某个子图用axs[index].scatter画散点图也没问题。
问题描述
但在之后,我需要画出2✖2的四个子图,且其中有散点图,我在上述1✖4的画图代码中改了一下运行后就报错了,具体如下:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg') # 为了避免matplotlib版本过高而报错,报错提示为:AttributeError: module 'backend_interagg' has no attribute 'FigureCanvas'
from matplotlib.font_manager import FontProperties
font_set = FontProperties(fname=r"c:/windows/fonts/HGXK_CNKI.TTF", size=12) # 为了在设置图的横纵轴标签上显示中文而不出现乱码
fig1, axs1 = plt.subplots(2, 2, figsize=(7, 7))
axs1[0].scatter(sequence_1, sequence_2, s=1) #sequence_1, sequence_2是我自己的数据,两个简单的列表
axs1[0].set_xlabel('t时刻状态编码', fontproperties=font_set) # fontproperties用来控制显示中文的字体
axs1[0].set_ylabel('t+1时刻状态编码', fontproperties=font_set)
x_axis = np.arange(1e6, 7e6, 1e6) # 控制坐标轴刻度,这里用的是float,不能用range(1e6, 7e6, 1e6),要用numpy的arange(1e6, 7e6, 1e6)
y_axis = np.arange(1e6, 7e6, 1e6)
axs1[0].set_xticks(x_axis) # 涉及到子图的能不能用.xticks(),而是得用.set_xticks()
axs1[0].set_yticks(y_axis)
axs1[1].scatter(sequence_11, sequence_22, s=1)
axs1[1].set_xlabel('t时刻状态编码', fontproperties=font_set)
axs1[1].set_ylabel('t+5时刻状态编码', fontproperties=font_set)
axs1[1].set_xticks(x_axis)
axs1[1].set_yticks(y_axis)
plt.subplots_adjust(hspace=0.3, wspace=0.3) # 调整子图之间的间距
plt.show()
结果会报错,如下:
AttributeError: 'numpy.ndarray' object has no attribute 'scatter'
我先还以为是scatter的问题,但是没查到和我类似的问题,我自己试了一下,很简单就找到原因了,分享一下我的方法。
解决方法
在子图变成有两行及以上后,每个子图的指定必须像矩阵一样,有行数和列数索引,即要变成axs1[0][0]、axs1[0][1]、axs1[1][0]、axs1[1][1],修改后能正常运行的部分相关代码如下所示:
axs1[0][0].scatter(sequence_1, sequence_2, s=1)
axs1[0][0].set_xlabel('t时刻状态编码', fontproperties=font_set)
axs1[0][0].set_ylabel('t+1时刻状态编码', fontproperties=font_set)
axs1[0][0].grid() # 画出网格
x_axis = np.arange(1e6, 7e6, 1e6)
y_axis = np.arange(1e6, 7e6, 1e6)
axs1[0][0].set_xticks(x_axis)
axs1[0][0].set_yticks(y_axis)
axs1[0][1].scatter(sequence_11, sequence_22, s=1)
axs1[0][1].set_xlabel('t时刻状态编码', fontproperties=font_set)
axs1[0][1].set_ylabel('t+5时刻状态编码', fontproperties=font_set)
axs1[0][1].grid()
axs1[0][1].set_xticks(x_axis)
axs1[0][1].set_yticks(y_axis)
axs1[1][0].scatter(sequence_111, sequence_222, s=1)
axs1[1][0].set_xlabel('t时刻状态编码', fontproperties=font_set)
axs1[1][0].set_ylabel('t+10时刻状态编码', fontproperties=font_set)
axs1[1][0].grid()
axs1[1][0].set_xticks(x_axis)
axs1[1][0].set_yticks(y_axis)
axs1[1][1].scatter(sequence_1111, sequence_2222, s=1)
axs1[1][1].set_xlabel('t时刻状态编码', fontproperties=font_set)
axs1[1][1].set_ylabel('t+20时刻状态编码', fontproperties=font_set)
axs1[1][1].grid()
axs1[1][1].set_xticks(x_axis)
axs1[1][1].set_yticks(y_axis)
最后显示的图像的效果如下图所示:
问题解决,结束。