【问题标题】:Recalculate x y values after zoom based on current ylim and xlim in Matplotlib根据 Matplotlib 中的当前 ylim 和 xlim 重新计算缩放后的 x y 值
【发布时间】:2021-07-29 12:52:40
【问题描述】:

亲爱的,我想重新计算写在我的图形刻度标签中的 x y 值,在我放大后,原点始终位于 (0,0) 并且显然值的相对距离x 和 y 轴保持不变。

我认为我需要在放大后跟踪我的数字的限制,而不是简单地从实际的 x y 刻度值中减去当前的 xmin 和 ymin。 我想这可以通过事件处理 API 来实现 Event handling 正如我在这里学到的: Source1

这也是我开始 MWE 的地方:

import matplotlib.pyplot as plt

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

#
# Scatter plot
fig, ax = plt.subplots(1, 1)
ax.scatter(x_seq, y_seq)


#
# Declare and register callbacks
def on_xlims_change(axes):
    a=axes.get_xlim()
    print "updated xlims: ", axes.get_xlim()
    return a
    
def on_ylims_change(axes):
    a=axes.get_ylim()
    print "updated ylims: ", axes.get_ylim()
    return a
    
ax.callbacks.connect('xlim_changed', on_xlims_change)
ax.callbacks.connect('ylim_changed', on_ylims_change)



#
# Show
plt.show()

但我真的不知道我应该如何离开这里?我是否必须在 on_xlims_change 函数内进行计算并在那里更改 x 和 y 刻度标签?同样,我认为我真的只需要更改标签中给出的值,对吗?还是更容易更改坐标的实际值以使自动刻度标签仍然有效?

【问题讨论】:

    标签: python matplotlib label


    【解决方案1】:

    这可能不像听起来那么容易。更改限制时,您将更改限制,使得回调无限运行,使您的窗口崩溃。

    因此,我会选择另一种解决方案,使用第二个轴。所以假设你有两个轴:

    • ax2 是要绘制的坐标轴。但是它没有框架,也没有刻度标签。这是您可以更改限制的坐标区。
    • ax 为空。它最初具有与ax2 相同的限制。它会显示刻度标签。

    放大ax2 后,回调函数可以根据自己的喜好更改ax 的限制。这就是屏​​幕上显示的内容。

    import matplotlib.pyplot as plt
    
    # Some toy data
    x_seq = [x / 100.0 for x in xrange(1, 100)]
    y_seq = [x**2 for x in x_seq]
    
    # ax is empty
    fig, ax = plt.subplots()
    ax.set_navigate(False)
    # ax2 will hold the plot, but has invisible labels
    ax2 = fig.add_subplot(111,zorder=2)
    ax2.scatter(x_seq, y_seq)
    ax2.axis("off")
    
    ax.set_xlim(ax2.get_xlim())
    ax.set_ylim(ax2.get_ylim())
    
    #
    # Declare and register callbacks
    def on_lims_change(axes):
        # change limits of ax, when ax2 limits are changed.
        a=ax2.get_xlim()
        ax.set_xlim(0, a[1]-a[0])
        a=ax2.get_ylim()
        ax.set_ylim(0, a[1]-a[0])
    
    ax2.callbacks.connect('xlim_changed', on_lims_change)
    ax2.callbacks.connect('ylim_changed', on_lims_change)
    
    # Show
    plt.show()
    

    【讨论】:

      【解决方案2】:

      您可以通过在on_ylims_change 内更新您的限制来实现您想要做的事情。但是,我们需要确保不会出现无限回调循环。一种方法是在我们更新xlimylim 时断开回调,然后立即重新连接。

      import matplotlib.pyplot as plt
      
      #
      # Some toy data
      x_seq = [x / 100.0 for x in range(1, 100)]
      y_seq = [x**2 for x in x_seq]
      
      #
      # Scatter plot
      fig, ax = plt.subplots(1, 1)
      ax.scatter(x_seq, y_seq)
      
      #
      # Declare and register callbacks
      def on_lims_change(event_ax):
          cid_list = list(event_ax.callbacks.callbacks['ylim_changed'].keys())
          for cid in cid_list:
              event_ax.callbacks.disconnect(cid)
          
          a = ax.get_xlim()
          span = a[1]-a[0]
          event_ax.set_xlim(-span/2, span/2)
          a = ax.get_ylim()
          span = a[1]-a[0]
          event_ax.set_ylim(-span/2, span/2)
          
          event_ax.callbacks.connect('ylim_changed', on_lims_change)
      
      
      ax.callbacks.connect('ylim_changed', on_lims_change)
      
      #
      # Show
      plt.show()
      

      通常我们只想连接到ylim_changed 事件,因为这将在xlim_changed 之后被调用以用于标准缩放事件。这样我们就可以在开始进行更改之前获得最终的缩放结果。

      【讨论】:

      • 这个答案的灵感来自@ImportanceOfBeingErnest 的答案,但我认为创建两个重叠轴并正确更新所有标签而无需额外代码会更容易一些。
      猜你喜欢
      • 1970-01-01
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-24
      • 2013-03-29
      • 1970-01-01
      相关资源
      最近更新 更多