【matplotlib】可视化解决方案——共享绘图区域问题

共享绘图区域问题

一.前言

有些时候我们会发现如果轴的范围不合适那么很难从图片中提取相应的信息,例如下方左图和有图很显然我们无法从中得出这二者密集程度的区别。除此之外很多时候我们想在一个坐标轴系统下展示两种不同的绘图,但是两者的轴域并不相同,这时候该怎么办呢?
绘图区域错误示例


我们再看一个示例,假设我们想在一个坐标轴绘制一个sin函数和一个cos函数,很显然下面的程序就能满足我们的需求。

fig, ax = plt.subplots(figsize=(10, 8))
x = np.linspace(0, 2*np.pi, 100)
ax.plot(np.sin(x), lw=2, color='c', label=r'$\sin({x})$')
ax.plot(np.cos(x), lw=2, color='k', label=r'$\cos({x})$')
ax.axhline(0, lw=4, color='r')
plt.grid(color='gray', ls=":")
plt.legend(loc='upper right', title=r'$\sin({x})$和$\cos({x})$示例', title_fontsize=12, shadow=True, fancybox=True, framealpha=0.8)
plt.show()

其画图结果如下:
画正弦和余弦函数
接下来,假设我们还是用同样的方法绘制20*sin(x)和cos(x)那么会发生什么呢?请看下图
20倍正弦函数和1倍余弦函数
我们可以看到为了能正常显示完整的正弦函数,整个余弦函数都已经被压缩,显然这样是无法达到我们想要的效果。但是我们观察可以看到,两者的定义域是一致的,只有值域是不相同的,也就是说两者可以共享一个X轴,但是不能使用同一个Y轴,这也就是我们要解决的问题,同样也是共享单一区域的坐标轴的实际意义。本文主要讨论这两类问题的解决方案,即共享单一区域的坐标轴共享不同子区绘图区域的坐标轴。文中代码只提供关键部分代码,导入必要的库以及库的初始化设置都已经省略。


二.解决方案

2.1共享单一区域的坐标轴解决方案

通过上面的例子我们已经知道解决这个问题的核心是如何共享X轴而不共享Y轴。我们可以使用twinx()方法制作并返回共享X轴的第二个轴系统。下面是该方法的定义:

twinx(ax=None)

参数1:ax:指定共享哪一个坐标轴系统
这里需要注意的是新的轴系统将会覆盖过去的轴系统,其Y轴刻度线和刻度标签在轴脊处生成。对于刚才的问题使用这个方法的代码如下:

fig, ax = plt.subplots(figsize=(10, 8))
x = np.linspace(0, 2*np.pi, 100)

line1 = ax.plot(20 * np.sin(x), lw=2, color='c', label=r'$\sin({x})$')
ax.axhline(0, lw=4, color='r')

ax2 = ax.twinx()
line2 = ax2.plot(np.cos(x), lw=2, color='k', label=r'$\cos({x})$')

plt.grid(color='gray', ls=":")
fig.suptitle(r'$\sin({x})$和$\cos({x})$示例', fontsize=20)
plt.show()

其画图结果如下:
共享一个画图区域
可以看到两者共享了X轴但是分别拥有自己的Y轴,大的轴会进行收缩以满足小的轴。这样我们在面对两个数据差距很大的图也能在单一区域进行绘制了。


2.1共享不同子区绘图区域的坐标轴解决方案

对于不同共享不同子区绘图区域有两种解决方案,第一种是使用set_xlim()set_ylim()方法手动修改坐标轴范围,当然修改共享区域只是这两个方法的冰山一角,单不妨碍我们达到我们想要的效果。示例代码如下:

x1 = np.linspace(-2*np.pi, 2*np.pi, 500)
y1 = np.cos(x1**2)

x2 = np.linspace(0.01, 10, 100)
y2 = np.sin(x2)

x3 = np.random.randint(0, 10, 50)
y3 = np.linspace(0, 3, 50)

x4 = np.random.randint(0, 25, 50)
y4 = np.linspace(0, 20, 50)

fig, ax = plt.subplots(1, 2)
fig.suptitle('使用set_xlim和set_ylim方法', fontsize=25)
ax[0].scatter(x3, y3)
ax[0].set_title("按照右图修改范围", fontsize=15)
ax[1].scatter(x4, y4)
ax[1].set_title('X轴取值:[-2, 25],Y轴取值:[-2, 20]', fontsize=15)
plt.subplots_adjust(wspace=0.6, top=0.8)

ax[0].set_xlim((-2, 25))
ax[0].set_ylim((-2, 20))

ax[1].set_xlim((-2, 25))
ax[1].set_ylim((-2, 20))
plt.show()

其画图结果如下:
使用set_xlim和set_ylim方法
从上图我们很容易看出两者谁的密集程度更大,相较于之前的错误示例这次的直观效果有了很大的提升。


第二种解决方案是在一开始的时候就指定好共享机制,即传递sharexsharey参数给subplots方法。示例代码如下:

x1 = np.linspace(-2*np.pi, 2*np.pi, 500)
y1 = np.cos(x1**2)

x2 = np.linspace(0.01, 10, 100)
y2 = np.sin(x2)

x3 = np.random.randint(0, 10, 50)
y3 = np.linspace(0, 3, 50)

x4 = np.random.randint(0, 25, 50)
y4 = np.linspace(0, 20, 50)

fig, ax = plt.subplots(1, 2, sharey=True, sharex=True)
fig.suptitle('使用set_xlim和set_ylim方法', fontsize=25)
ax[0].scatter(x3, y3)
ax[0].set_title("按照右图修改范围", fontsize=15)
ax[1].scatter(x4, y4)
ax[1].set_title('X轴取值:[-2, 25],Y轴取值:[-2, 20]', fontsize=15)
plt.subplots_adjust(wspace=0.6, top=0.8)

plt.show()

其画图结果如下:
传递sharex和sharey参数
可以看到这两种方法的效果是一致的。这两个参数一共有五个有效值,分别是:

  1. True/‘all’:所有的子区都享有同一个坐标轴系统
  2. ‘col’:指定子区中的每一列都想有同样的坐标轴系统
  3. ‘row’:指定子区中的每一行都想有同样的坐标轴系统
  4. False/‘none’:不共享
  5. ax:指定一个子区,这样就可以单独指定任意两个子区共享坐标轴系统

一定切记共享的坐标轴系统都是所有子区中的最大值。即可能出现X轴和Y轴不来自一个子区的情况。


三.参考

  1. 可视化解决方案
  2. 可视化之路
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猪猪家的大猪猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值