Matplotlib附加坐标轴上的刻度位置错误

7

我希望能够在图表中添加一个上部X轴,使其刻度与原始X轴相同(刻度标签可能不同)。看起来这很容易实现,但我不确定为什么下面的代码无法实现:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(111)

X = np.linspace(11,80,1000)
Y = 2*np.sin(X)*np.exp(-X/20.)

ax1.plot(X,Y)
ax2 = ax1.twiny()

old_ticks = ax1.get_xticks()
ax2.set_xticks(old_ticks)

plt.show()

以下是翻译的结果:

输出如下所示:显然,顶部轴上的刻度位置与下方轴上的刻度不同(即在顶部轴上有7个刻度,而底部只有6个)。

为什么会这样呢?

第二个x轴上的偏移刻度

编辑:设置xlim(如下面所建议的)仅适用于初始绘图,但不适用于缩放到不同区域时。我添加了一个回调函数,以在缩放时将ax2上的刻度添加到与ax1上的刻度相同的位置,但似乎不起作用。

此外,我使用twiny是因为最终显示的ax2刻度值将以非线性方式取决于ax1刻度值。我只希望刻度在轴上的位置相同。 import numpy as np import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(111)

X = np.linspace(11,80,1000)
Y = 2*np.sin(X)*np.exp(-X/20.)

ax1.plot(X,Y)
ax2 = ax1.twiny()

ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(ax1.get_xticks())

def on_xlim_changed(ax1):
    ax2.set_xlim(ax1.get_xlim())
    ax2.set_xticks(ax1.get_xticks())

ax1.callbacks.connect('xlim_changed',on_xlim_changed)

plt.show()

好问题,可以说已经过去了六年,网络上仍然没有简单的答案。在您的第二个示例代码中,如果交换这两行,您将获得一个不错的初始图形,但缩放确实会导致刻度变得不对齐:ax2.set_xlim(ax1.get_xlim()) ax2.set_xticks(ax1.get_xticks()) 一些可能有帮助的帖子(也在我的赏金描述中):stackoverflow.com/a/35904761/2542091 stackoverflow.com/a/27344398/2542091 - Aleksander Lidtke
3个回答

5

尝试:

ax2.set_xlim(ax1.get_xlim())

此外,如果您只需要在顶部显示刻度线,则无需添加twiny轴,您可以直接使用以下代码: ax.xaxis.tick_top()。该代码保留了html标签,如有需要请自行删除。
ax1.xaxis.set_ticks_position('both')

2
这似乎只在图形最初显示时有效,而不是当我们缩放到图形的不同区域时。我想使用 twiny 的原因是我希望刻度线与底部轴上的位置相同,但刻度标签将不同。我编辑了我的问题以包括“缩放”澄清。 - Ron OGara
@behzad.nouri 由于某种原因,set_ticks_postion('both') 在 matplotlib '3.1.3' 中无法正常工作。可以将它们设置为 topbottom(Y 轴的 leftright),但不能设置为 bothnone - Aleksander Lidtke
@RonOGara 上面建议的 ax2.set_xlim(ax1.get_xlim()) 对我来说很有效,即使在平移或缩放的情况下也是如此。 - Zephyr

3
这里的技巧是使用ax2.set_navigate(False)禁用次要轴上的缩放。只有在缩放不影响轴本身的限制时,调整回调中的限制才会产生影响:
import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(111)

x = np.linspace(11, 80, 1000)
y = 2 * np.sin(x) * np.exp(-x / 20.)

ax1.plot(x, y)
ax2 = ax1.twiny()
ax2.set_navigate(False)  # Important!

old_ticks = ax1.get_xticks()
ax2.set_xticks(old_ticks)
ax1.grid(linewidth=1, ls='--') # Added to be able to see the (mis-)alignment better.

ax2.set_xlim(ax1.get_xlim())

def on_xlim_changed(ax_):
    ax2.set_xticks(ax_.get_xticks())
    ax2.set_xlim(ax_.get_xlim())

ax1.callbacks.connect('xlim_changed', on_xlim_changed)

plt.show()

没有使用set_navigate(False)的缩放示例

在不使用<code>set_navigate(False)</code>的情况下进行缩放

使用答案中发布的代码进行缩放

使用答案中发布的代码进行缩放


这很简单,对吧?;) 太棒了!非常感谢! - Aleksander Lidtke

0

你应该使用 Locator 功能

import matplotlib.ticker as mticks

N = 5
ax1.get_xaxis().set_major_locator(mticks.LinearLocator(numticks=N))
ax2.get_xaxis().set_major_locator(mticks.LinearLocator(numticks=hN))

(doc) 这将在坐标轴上放置N个均匀分布的刻度。

Formatter将负责格式化标签。

请注意,这可能会导致标签看起来非常奇怪。位置跳动的原因是AutoLocator是默认定位器,试图将刻度放在“好看”的位置(整数、偶数倍等),以便您不会得到看起来像“1.52547841082”的刻度标签。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接