【1】引言
在前述学习中,对使用matplotlib模块输出图形已经非常熟练,但常见的画图方式并未穷尽,如两个Y轴共享X轴就没有探索过。
对此,我进行了一些学习,获得一些心得,在此和大家共享。
【2】官网教程
官网对两个Y轴共享X轴提供了详细解释和代码示例,可以通过下述链接直达:
https://matplotlib.org/stable/gallery/subplots_axes_and_figures/two_scales.html#sphx-glr-gallery-subplots-axes-and-figures-two-scales-py
为便于大家理解和阅读,我增添了代码注释。
【3】代码解读
首先是引入画图模块和计算模块:matplotlib和numpy
import matplotlib.pyplot as plt #引入画图模块 import numpy as np #引入计算模块
然后定义自变量和因变量:
t = np.arange(0.01, 10.0, 0.01) #定义自变量 data1 = np.exp(t) #定义因变量 data2 = np.sin(2 * np.pi * t) #定义因变量
之后定义了要画图:
fig, ax1 = plt.subplots() #定义要画图
首先进行第一个图的定义:
fig, ax1 = plt.subplots() #定义要画图 color = 'tab:red' #设置颜色变量 ax1.set_xlabel('time (s)') #设置X轴标签 ax1.set_ylabel('exp', color=color) #设置Y轴标签 ax1.plot(t, data1, color=color) #输出图形 ax1.tick_params(axis='y', labelcolor=color) #设置Y轴颜色
然后进行第二个图的定义:
ax2 = ax1.twinx() # instantiate a second Axes that shares the same x-axis color = 'tab:blue' ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1 #设置Y轴标签 ax2.plot(t, data2, color=color) #输出图形 ax2.tick_params(axis='y', labelcolor=color) #输出图形
最后输出图形:
fig.tight_layout() # otherwise the right y-label is slightly clipped #可以保证Y轴标签位置合理,不会和坐标轴重合 plt.show() #输出图形
图形输出结果为:
图1
【4】代码修改
在【3】中可以发现,ax1是用subplots()函数进行的定义,ax2是用ax1.twinx()函数完成的定义。
为此,最核心的函数就是ax1.twinx()。
为了测试该功能,修改ax定义程序为:
import matplotlib.pyplot as plt #引入画图模块
import numpy as np #引入计算模块
# Create some mock data
t = np.arange(0.01, 10.0, 0.01) #定义自变量
data1 = np.exp(t) #定义因变量
data2 = np.sin(2 * np.pi * t) #定义因变量
fig, ax = plt.subplots(2,1) #定义要画图
color = 'tab:red' #设置颜色变量
ax[0].set_xlabel('time (s)') #设置X轴标签
ax[0].set_ylabel('exp', color=color) #设置Y轴标签
ax[0].plot(t, data1, color=color) #输出图形
ax[0].tick_params(axis='y', labelcolor=color) #设置Y轴颜色
#ax2 = plt.subplots() # instantiate a second Axes that shares the same x-axis
color = 'tab:blue'
ax[1].set_ylabel('sin', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax[1].plot(t, data2, color=color) #输出图形
ax[1].tick_params(axis='y', labelcolor=color) #输出图形
fig.tight_layout() # otherwise the right y-label is slightly clipped #可以保证Y轴标签位置合理,不会和坐标轴重合
plt.show() #输出图形
上述代码的ax定义部分已经全部修改为subplots()输出:
fig, ax = plt.subplots(2,1) #定义要画图 color = 'tab:red' #设置颜色变量 ax[0].set_xlabel('time (s)') #设置X轴标签 ax[0].set_ylabel('exp', color=color) #设置Y轴标签 ax[0].plot(t, data1, color=color) #输出图形 ax[0].tick_params(axis='y', labelcolor=color) #设置Y轴颜色 #ax2 = plt.subplots() # instantiate a second Axes that shares the same x-axis color = 'tab:blue' ax[1].set_ylabel('sin', color=color) # we already handled the x-label with ax1 #设置Y轴标签 ax[1].plot(t, data2, color=color) #输出图形 ax[1].tick_params(axis='y', labelcolor=color) #输出图形
此时的输出结果为:
图2
至此,测试结果很清晰,使用twinx()函数可以实现2个Y轴共享X轴。
【5】代码改写
【5.1】 ax.twinx()函数测试
进一步测试,引入第三个变量:
data3 = 12*np.cos(2 * np.pi * t) #定义因变量
在此基础上,有两种共享Y轴的方式,一种是ax3 = ax1.twinx(),一种是ax3 = ax2.twinx(),第一种的完整代码为:
import matplotlib.pyplot as plt #引入画图模块
import numpy as np #引入计算模块
# Create some mock data
t = np.arange(0.01, 10.0, 0.01) #定义自变量
data1 = np.exp(t) #定义因变量
data2 = np.sin(2 * np.pi * t) #定义因变量
data3 = 12*np.cos(2 * np.pi * t) #定义因变量
fig, ax1 = plt.subplots() #定义要画图
color = 'tab:red' #设置颜色变量
ax1.set_xlabel('time (s)') #设置X轴标签
ax1.set_ylabel('exp', color=color) #设置Y轴标签
ax1.plot(t, data1, color=color) #输出图形
ax1.tick_params(axis='y', labelcolor=color) #设置Y轴颜色
ax2 = ax1.twinx() # instantiate a second Axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax2.plot(t, data2, color=color) #输出图形
ax2.tick_params(axis='y', labelcolor=color) #输出图形
ax3 = ax1.twinx() # instantiate a second Axes that shares the same x-axis
color = 'tab:green'
ax3.set_ylabel('cos', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax3.plot(t, data3, color=color) #输出图形
ax3.tick_params(axis='y', labelcolor=color) #输出图形
fig.tight_layout() # otherwise the right y-label is slightly clipped #可以保证Y轴标签位置合理,不会和坐标轴重合
plt.show() #输出图形
对应输出结果为:
图3
可见共享X轴的两个Y轴按照各自的比例,将图像放大,铺满了坐标轴。
第二种方式的完整代码为:
import matplotlib.pyplot as plt #引入画图模块
import numpy as np #引入计算模块
# Create some mock data
t = np.arange(0.01, 10.0, 0.01) #定义自变量
data1 = np.exp(t) #定义因变量
data2 = np.sin(2 * np.pi * t) #定义因变量
data3 = 12*np.cos(2 * np.pi * t) #定义因变量
fig, ax1 = plt.subplots() #定义要画图
color = 'tab:red' #设置颜色变量
ax1.set_xlabel('time (s)') #设置X轴标签
ax1.set_ylabel('exp', color=color) #设置Y轴标签
ax1.plot(t, data1, color=color) #输出图形
ax1.tick_params(axis='y', labelcolor=color) #设置Y轴颜色
ax2 = ax1.twinx() # instantiate a second Axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax2.plot(t, data2, color=color) #输出图形
ax2.tick_params(axis='y', labelcolor=color) #输出图形
ax3 = ax2.twinx() # instantiate a second Axes that shares the same x-axis
color = 'tab:green'
ax3.set_ylabel('cos', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax3.plot(t, data3, color=color) #输出图形
ax3.tick_params(axis='y', labelcolor=color) #输出图形
fig.tight_layout() # otherwise the right y-label is slightly clipped #可以保证Y轴标签位置合理,不会和坐标轴重合
plt.show() #输出图形
对应输出结果为:
图4
由图4可见,ax2对应的Y轴数据自动移动到了左侧。
也就是:
ax1.twinx()时,ax1的Y值会出现在左侧Y轴;ax2.twinx()时,ax2的Y值会出现在左侧Y轴。
【5.2】 自变量范围扩大测试
进一步测试,设置新自变量:
n = np.arange(10.0,20.0,0.01) #定义新自变量
对应设置新因变量:
data3 = np.sin(2 * np.pi * n) #定义新因变量
此处采用ax1.twinx()进行X轴共享,获得的输出图形为:
图5
由图5可见,共享X轴可以在自变量取值不重合的前提下实施。
但需注意的是,如果心得自变量data3在输出的时候,Y轴设置名称是其他,比如“cos”,就会出现cos和sin的重影。
图6
由图6可见,出现了Y轴标签的重影。
此时的完整代码为:
import matplotlib.pyplot as plt #引入画图模块
import numpy as np #引入计算模块
# Create some mock data
t = np.arange(0.01, 10.0, 0.01) #定义自变量
n = np.arange(10.0,20.0,0.01) #定义新自变量
data1 = np.exp(t) #定义因变量
data2 = np.sin(2 * np.pi * t) #定义因变量
data3 = np.sin(2 * np.pi * n) #定义新因变量
fig, ax1 = plt.subplots() #定义要画图
color = 'tab:red' #设置颜色变量
ax1.set_xlabel('time (s)') #设置X轴标签
ax1.set_ylabel('exp', color=color) #设置Y轴标签
ax1.plot(t, data1, color=color) #输出图形
ax1.tick_params(axis='y', labelcolor=color) #设置Y轴颜色
ax2 = ax1.twinx() # instantiate a second Axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax2.plot(t, data2, color=color) #输出图形
ax2.tick_params(axis='y', labelcolor=color) #输出图形
ax3 = ax1.twinx() # instantiate a second Axes that shares the same x-axis
color = 'tab:green'
ax3.set_ylabel('cos', color=color) # we already handled the x-label with ax1 #设置Y轴标签
ax3.plot(n, data3, color=color) #输出图形
ax3.tick_params(axis='y', labelcolor=color) #输出图形
ax3.set_title('Y share X')
fig.tight_layout() # otherwise the right y-label is slightly clipped #可以保证Y轴标签位置合理,不会和坐标轴重合
plt.show() #输出图形
【6】总结
学习了两个Y轴共享X轴的基础教程,尝试探索了3个Y轴共享X轴。