如何在Matplotlib中添加第二个X轴


78

我有一个非常简单的问题。我需要在绘图上有第二个x轴,并且我希望该轴具有一定数量的tic,它们对应于第一个轴的特定位置。

让我们尝试一个例子。在这里,我将暗物质质量绘制为膨胀系数(定义为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?如果是这样,该问题如何在matplotlib中绘制多个x或y轴?似乎涵盖了这一点。
詹姆斯

Answers:


115

我正在从@Dhara答案中的注释中获取线索,这听起来像是您要按new_tick_locations功能设置从旧x轴到新x轴的列表。在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()

在此处输入图片说明


2
如果你想添加一个标题为好,看这个问题:stackoverflow.com/questions/12750355/...
szmoore

@Hooked,如果有可能使用对数刻度中的一种刻度,是否有可能?
tiago

2
@tiago我现在无法检查,但是ax.set_yscale('log')行得通吗?
上钩

5
由于xlim在0到1之间(默认值),因此本示例“偶然”工作。为了使这项工作适用于任意限制,还需要确保两个轴的限制与类似的东西匹配,ax2.set_xlim(ax1.get_xlim())否则X顶部的和X底部的将会不同。
mforbes

Matplotlib实现了一种添加辅助轴的本地方法。在这里看到的例子:matplotlib.org/3.1.0/gallery/subplots_axes_and_figures/...
斯蒂法诺

27

您可以使用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轴上的某些特殊位置上打勾即可。
布莱恩

然后,只需添加具有所需范围的虚拟第二轴并清除即可。看到我编辑过的答案
达拉(Dhara)

抱歉,您的代码无效。我复制并粘贴了它,然后第二个x轴与第一个x轴重叠。
布莱恩

附加输出,这不是您想要/想要的吗?
达拉

并不是的。以您的示例为参考,我想在第二个x轴上显示这些曲线:(7,8,99)对应于x轴位置10、30、40。
布莱恩

12

如果您希望上轴是下轴刻度值的函数:

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()
ax1Xs = ax1.get_xticks()

ax2Xs = []
for X in ax1Xs:
    ax2Xs.append(X * 2)

ax2.set_xticks(ax1Xs)
ax2.set_xbound(ax1.get_xbound())
ax2.set_xticklabels(ax2Xs)

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")

给出:

在此处输入图片说明


11

在Dhara的回答中回答您的问题:“我想在第二个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()

你会得到: 在此处输入图片说明


3

从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()


2

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

ax2.lines = []

而不是使用:

ax2.cla()

使用时也从中清除了我的情节ax1


3
如果提供了代码示例,这将是一个更好的答案,而不仅仅是Dhara答案的更改。
本杰明
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.