要在交互式Matplotlib的双(子)图中同步双x轴?

时间:2019-10-16 14:35:50

标签: python matplotlib

基本上,我希望达到与https://stackoverflow.com/a/58413766/6197439相同的功能-除了两个图以外。

此示例代码粘贴在下面,这是其行为的动画gif:

Figure_1

问题是:

  • 我必须将双轴设为twiny的{​​{1}}(底部子图),以便将其绘制在底部共享x轴的下方,否则将绘制在顶部图的下方(并且与底部图的顶部重叠)
  • 开始之后,我首先在底部子图中拖动-两个轴都按照其应有的方向
  • 如果我放大底部子图,则两个x轴都可以正确缩放-但是双轴没有所有标签(这就是为什么我有ax2,这有助于在链接的帖子中修复该问题,只有一个地块-但在这里我无法使它正常工作
  • 如果然后我在顶部子图中拖动-仅原始x轴移动,双/孪生克隆x轴不会移动(gif并没有显示出来,但是在顶部子图中放大也是如此)

我尝试对on_xlims_changeax都使用回调,但无法获得改进的行为-但是,请注意gif显示的行为与此处发布的代码相同(其中不使用回调)。

那么,如何使双/孪生x轴遵循原始共享x轴-在顶部和底部子图中同时缩放和平移?

代码:

ax2

1 个答案:

答案 0 :(得分:0)

我想我有一个解决方案(下面的代码):

Figure_1

....感谢@ImportanceOfBeingErnest的评论:

  

axes.get_xticks()让您在更改之前 之前打勾。

好吧,现在至少是有道理的,为什么设置它如此困难:)希望我早先找到此信息...人们似乎对此有疑问:

  

我想我会尝试共享所有三个轴

我发现的唯一信息是:

显然,人们可以使用ax1.get_shared_x_axes().join(ax1, ax2)->但是,这种联接不是在Python中将数组“联接”为字符串的意义上,也不是在附加到数组的意义上,而是(dis)join(t)集的意义,显然,因此您可以加入三个项目,这是我尝试过的(似乎可行):

ax.get_shared_x_axes().join(ax, ax2, ax22)

这正确吗?

  

,然后在最后一个上使用不同的格式化程序。

这里有不错的信息:

所以,最后,我的代码是:

#!/usr/bin/env python3

import matplotlib
print("matplotlib.__version__ {}".format(matplotlib.__version__))
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

#
# Some toy data
x_seq = [x / 100.0 for x in range(1, 100)]
y_seq = [x**2 for x in x_seq]
y2_seq = [0.3*x**2 for x in x_seq]

#
# Scatter plot
fig, (ax, ax2) = plt.subplots(2, 1, sharex=True, figsize=(9, 6), dpi=100, gridspec_kw={'height_ratios': [2, 1]}) # two rows, one column
# Remove horizontal space between axes
fig.subplots_adjust(hspace=0)

# https://stackoverflow.com/questions/31803817/how-to-add-second-x-axis-at-the-bottom-of-the-first-one-in-matplotlib
ax22 = ax2.twiny() # instantiate a second axes that shares the same y-axis
#~ ax.get_shared_x_axes().join(ax, ax22) # SO:42718823
ax.get_shared_x_axes().join(ax, ax2, ax22)
#~ ax.autoscale() # <-- needed if no axes limits are explicitely set. SO:42718823
# Move twinned axis ticks and label from top to bottom
ax22.xaxis.set_ticks_position("bottom")
ax22.xaxis.set_label_position("bottom")
# Offset the twin axis below the host
ax22.spines["bottom"].set_position(("axes", -0.1))

ax.plot(x_seq, y_seq)
ax2.plot(x_seq, y2_seq)

factor = 655

# FuncFormatter can be used as a decorator
@ticker.FuncFormatter
def major_formatter(x, pos):
  #return "[%.2f]" % x
  return int(factor*x)

ax22.xaxis.set_major_formatter(major_formatter)

#
# Show
plt.show()