【问题标题】:How to add a second x-axis in matplotlib如何在 matplotlib 中添加第二个 x 轴
【发布时间】:2012-05-17 20:43:34
【问题描述】:

我有一个非常简单的问题。我需要在我的绘图上有第二个 x 轴,并且我希望这个轴有一定数量的抽动,对应于第一个轴的某个位置。

让我们举个例子。在这里,我将暗物质质量绘制为膨胀因子的函数,定义为 1/(1+z),范围从 0 到 1。

semilogy(1/(1+z),mass_acc_massive,'-',label='DM')
xlim(0,1)
ylim(1e8,5e12)

我想在我的绘图顶部有另一个 x 轴,显示扩展因子的某些值对应的 z。那可能吗?如果是,我怎样才能拥有 xtics 斧头

【问题讨论】:

标签: python matplotlib


【解决方案1】:

如果您希望上轴成为下轴刻度值的函数,您可以执行以下操作。请注意:有时get_xticks() 会有一个超出可见范围的刻度,转换时必须允许。

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots()

ax1 = fig.add_subplot(111)

ax1.plot(range(5), range(5))

ax1.grid(True)

ax2 = ax1.twiny()
ax2.set_xticks( ax1.get_xticks() )
ax2.set_xbound(ax1.get_xbound())
ax2.set_xticklabels([x * 2 for x in ax1.get_xticks()])

title = ax1.set_title("Upper x-axis ticks are lower x-axis ticks doubled!")
title.set_y(1.1)
fig.subplots_adjust(top=0.85)

fig.savefig("1.png")

给予:

【讨论】:

  • ax2.set_xticks(ax1Xs) ...这是什么?
  • @jaromrax: 那是ax1.get_xticks();代码是用 python3.4 和 matplotlib1.4 编写的——从那时起,matplotlib 发生了很大变化。
【解决方案2】:

从 matplotlib 3.1 开始,您可以使用 ax.secondary_xaxis

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(1,13, num=301)
y = (np.sin(x)+1.01)*3000

# Define function and its inverse
f = lambda x: 1/(1+x)
g = lambda x: 1/x-1

fig, ax = plt.subplots()
ax.semilogy(x, y, label='DM')

ax2 = ax.secondary_xaxis("top", functions=(f,g))

ax2.set_xlabel("1/(x+1)")
ax.set_xlabel("x")
plt.show()

【讨论】:

    【解决方案3】:

    我从@Dhara 的答案中的 cmets 中得到提示,听起来您想通过从旧 x 轴到新 x 轴的函数设置new_tick_locations 列表。下面的 tick_function 接受一个 numpy 点数组,将它们映射到一个新值并格式化它们:

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax2 = ax1.twiny()
    
    X = np.linspace(0,1,1000)
    Y = np.cos(X*20)
    
    ax1.plot(X,Y)
    ax1.set_xlabel(r"Original x-axis: $X$")
    
    new_tick_locations = np.array([.2, .5, .9])
    
    def tick_function(X):
        V = 1/(1+X)
        return ["%.3f" % z for z in V]
    
    ax2.set_xlim(ax1.get_xlim())
    ax2.set_xticks(new_tick_locations)
    ax2.set_xticklabels(tick_function(new_tick_locations))
    ax2.set_xlabel(r"Modified x-axis: $1/(1+X)$")
    plt.show()
    

    【讨论】:

    • 如果您也想添加标题,请参阅此问题:stackoverflow.com/questions/12750355/…
    • @Hooked,知道是否可以使用对数刻度中的一种刻度来做到这一点?
    • @tiago 我现在无法检查,但ax.set_yscale('log') 有效吗?
    • 这个例子是“偶然”的,因为 xlims 介于 0 和 1 之间(默认值)。要使这项工作适用于任意限制,还需要确保两个轴的限制与 ax2.set_xlim(ax1.get_xlim()) 之类的匹配,否则顶部的 X 和底部的 X 会有所不同。
    • Matplotlib 实现了一种原生方式来添加辅助轴。在此处查看他们的示例:matplotlib.org/3.1.0/gallery/subplots_axes_and_figures/…
    【解决方案4】:

    由于声誉低下,我不得不将此作为答案而不是评论发布。 我遇到了与 Matteo 类似的问题。不同之处在于我没有从第一个 x 轴到第二个 x 轴的映射,只有 x 值本身。所以我想直接在我的第二个 x 轴上设置数据,而不是刻度,但是,没有axes.set_xdata。我可以使用 Dhara 的答案进行修改:

    ax2.lines = []
    

    而不是使用:

    ax2.cla()
    

    在使用时还从ax1 清除了我的情节。

    【讨论】:

    • 如果您提供代码示例,这将是一个更好的答案,而不仅仅是 Dhara 答案的更改。
    【解决方案5】:

    在 Dhara 的回答 cmets 中回答您的问题:“我想在第二个 x 轴上这些抽动:(7,8,99) 对应于 x 轴位置 10,30,40。这可能吗以某种方式?" 是的。

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    
    a = np.cos(2*np.pi*np.linspace(0, 1, 60.))
    ax1.plot(range(60), a)
    
    ax1.set_xlim(0, 60)
    ax1.set_xlabel("x")
    ax1.set_ylabel("y")
    
    ax2 = ax1.twiny()
    ax2.set_xlabel("x-transformed")
    ax2.set_xlim(0, 60)
    ax2.set_xticks([10, 30, 40])
    ax2.set_xticklabels(['7','8','99'])
    
    plt.show()
    

    您将获得:

    【讨论】:

      【解决方案6】:

      您可以使用 twiny 创建 2 个 x 轴刻度。例如:

      import numpy as np
      import matplotlib.pyplot as plt
      
      fig = plt.figure()
      ax1 = fig.add_subplot(111)
      ax2 = ax1.twiny()
      
      a = np.cos(2*np.pi*np.linspace(0, 1, 60.))
      
      ax1.plot(range(60), a)
      ax2.plot(range(100), np.ones(100)) # Create a dummy plot
      ax2.cla()
      plt.show()
      

      参考:http://matplotlib.sourceforge.net/faq/howto_faq.html#multiple-y-axis-scales

      输出:

      【讨论】:

      • 我很抱歉,但这不是我所要求的。我不需要在具有不同轴的同一图上绘制函数。我只需要在我的绘图顶部有第二个 x 轴,对应第一个 x 轴上的某个特殊位置。
      • 然后只需添加一个具有您想要的范围的虚拟第二轴并清除它。查看我编辑的答案
      • 抱歉,您的代码不起作用。我复制并粘贴了它,然后第二个 x 轴与第一个重叠。
      • 附加输出,这不是你得到/想要的吗?
      • 并非如此。以您的示例作为参考,我希望在第二个 x 轴上这些抽动:(7,8,99) 对应于 x 轴位置 10、30、40。这可能以某种方式吗?
      猜你喜欢
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 2019-10-02
      相关资源
      最近更新 更多