[英]How to add a second x-axis in matplotlib
I have a very simple question.我有一个非常简单的问题。 I need to have a second x-axis on my plot and I want that this axis has a certain number of tics that correspond to certain position of the first axis.
我需要在我的绘图上有第二个 x 轴,我希望这个轴有一定数量的 tic,对应于第一个轴的某个位置。
Let's try with an example.让我们用一个例子来试试。 Here I am plotting the dark matter mass as a function of the expansion factor, defined as 1/(1+z), that ranges from 0 to 1.
在这里,我将暗物质质量绘制为膨胀因子的函数,定义为 1/(1+z),范围从 0 到 1。
semilogy(1/(1+z),mass_acc_massive,'-',label='DM')
xlim(0,1)
ylim(1e8,5e12)
I would like to have another x-axis, on the top of my plot, showing the corresponding z for some values of the expansion factor.我想在图的顶部有另一个 x 轴,显示某些扩展因子值的相应 z。 Is that possible?
那可能吗? If yes, how can I have xtics ax
如果是,我怎么能有 xtics ax
I'm taking a cue from the comments in @Dhara's answer, it sounds like you want to set a list of new_tick_locations
by a function from the old x-axis to the new x-axis.我从@Dhara 的回答中的评论中得到了一个提示,听起来您想通过从旧 x 轴到新 x 轴的函数设置
new_tick_locations
列表。 The tick_function
below takes in a numpy array of points, maps them to a new value and formats them:下面的
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()
You can use twiny to create 2 x-axis scales.您可以使用 twiny 创建 2 个 x 轴比例。 For Example:
例如:
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()
Ref: http://matplotlib.sourceforge.net/faq/howto_faq.html#multiple-y-axis-scales参考: http : //matplotlib.sourceforge.net/faq/howto_faq.html#multiple-y-axis-scales
Output:输出:
If You want your upper axis to be a function of the lower axis tick-values you can do as below.如果您希望上轴是下轴刻度值的函数,您可以执行以下操作。 Please note: sometimes
get_xticks()
will have a ticks outside of the visible range, which you have to allow for when converting.请注意:有时
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")
Gives:给出:
Answering your question in Dhara's answer comments: " I would like on the second x-axis these tics: (7,8,99) corresponding to the x-axis position 10, 30, 40. Is that possible in some way? " Yes, it is.在 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()
You'll get:你会得到:
From matplotlib 3.1 onwards you may use ax.secondary_xaxis
从 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()
I'm forced to post this as an answer instead of a comment due to low reputation.由于声誉低,我被迫将此作为答案而不是评论发布。 I had a similar problem to Matteo.
我遇到了与 Matteo 类似的问题。 The difference being that I had no map from my first x-axis to my second x-axis, only the x-values themselves.
不同之处在于我没有从第一个 x 轴到第二个 x 轴的映射,只有 x 值本身。 So I wanted to set the data on my second x-axis directly, not the ticks, however, there is no
axes.set_xdata
.所以我想直接在我的第二个 x 轴上设置数据,而不是刻度,但是,没有
axes.set_xdata
。 I was able to use Dhara's answer to do this with a modification:我能够使用 Dhara 的答案通过修改来做到这一点:
ax2.lines = []
instead of using:而不是使用:
ax2.cla()
When in use also cleared my plot from ax1
.在使用时也从
ax1
清除了我的情节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.