Python 对数图中的寄生x轴

Python 对数图中的寄生x轴,python,matplotlib,axis,loglog,Python,Matplotlib,Axis,Loglog,我有一个图表,其中x轴是以GeV为单位的温度,但我还需要以开尔文为单位的温度参考,所以我想用温度为K的寄生轴。为了遵循这个答案,下面是代码示例。我在图的顶部得到了第二个轴,但它不是我需要的温度,单位是K import numpy as np import matplotlib.pyplot as plt tt = np.logspace(-14,10,100) yy = np.logspace(-10,-2,100) fig = plt.figure() ax1 = fig.add_subp

我有一个图表,其中x轴是以GeV为单位的温度,但我还需要以开尔文为单位的温度参考,所以我想用温度为K的寄生轴。为了遵循这个答案,下面是代码示例。我在图的顶部得到了第二个轴,但它不是我需要的温度,单位是K

import numpy as np
import matplotlib.pyplot as plt

tt = np.logspace(-14,10,100)
yy = np.logspace(-10,-2,100)

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

ax1.loglog(tt,yy)
ax1.set_xlabel('Temperature (GeV')

new_tick_locations = np.array([.2, .5, .9])

def tick_function(X):
    V = X*1.16e13
    return ["%.1f" % z for z in V]

ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(ax1Xs))
ax2.set_xlabel('Temp (Kelvin)')
plt.show()
这是我运行代码时得到的结果

对数图


我需要寄生虫轴与原始x轴成比例。当任何人看到图表时,都可以很容易地读取以开尔文为单位的温度。提前感谢。

问题似乎如下:当您使用
ax2.set_xlim(ax1.get_xlim())
时,您基本上是将x轴上限设置为与x轴下限相同。现在如果你这样做了

print(ax1.get_xlim()) 
print(ax2.get_xlim()) 
两个轴的值都相同

(6.309573444801943e-16, 158489319246.11108) 
(6.309573444801943e-16, 158489319246.11108) 
但是你的下x轴有一个对数刻度。当您使用
ax2.setxlim()
指定限制时,
ax2
的限制相同,但比例仍然是线性的。这就是为什么当您将刻度设置为
[.2、.5、.9]
时,这些值显示为x轴上部最左侧的刻度,如图所示

解决方案是将上x轴也设置为对数刻度。这是必需的,因为您的
新标记位置
对应于下部x轴上的实际值。您只需要重命名这些值,以开尔文显示标签。从变量名中可以清楚地看出,
新勾号位置
对应于新的勾号位置。我使用了一些修改后的
new\u tick\u locations
值来突出问题

我使用的是科学格式
'%.0e'
,因为1gev=1.16e13k,所以0.5gev将是一个非常大的值,有许多零

以下是一个示例答案:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick

tt = np.logspace(-14,10,100)
yy = np.logspace(-10,-2,100)

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

ax1.loglog(tt,yy)
ax1.set_xlabel('Temperature (GeV)')

new_tick_locations = np.array([0.000002, 0.05, 9000])

def tick_function(X):
    V = X*1.16e13
    return ["%.1f" % z for z in V]

ax2.set_xscale('log') # Setting the logarithmic scale
ax2.set_xlim(ax1.get_xlim())

ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(new_tick_locations))
ax2.xaxis.set_major_formatter(mtick.FormatStrFormatter('%.0e'))

ax2.set_xlabel('Temp (Kelvin)')
plt.show()

通用解决方案可能如下所示。因为你有一个非线性的刻度,我们的想法是用开尔文找到好的刻度的位置,转换成GeV,用GeV的单位设置位置,但用开尔文的单位标记它们。这听起来很复杂,但优点是您不需要自己查找刻度,只需依靠matplotlib查找刻度。 但这需要的是两个尺度之间的函数依赖性,即GeV和开尔文之间的转换及其逆

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

tt = np.logspace(-14,10,100)
yy = np.logspace(-10,-2,100)

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

plt.setp([ax1,ax2], xscale="log", yscale="log")
ax1.get_shared_x_axes().join(ax1, ax2)

ax1.plot(tt,yy)

ax1.set_xlabel('Temperature (GeV)')
ax2.set_xlabel('Temp (Kelvin)')

fig.canvas.draw()

# 1 GeV == 1.16 × 10^13 Kelvin
Kelvin2GeV = lambda k:  k / 1.16e13
GeV2Kelvin = lambda gev: gev * 1.16e13

loc = mticker.LogLocator()
locs = loc.tick_values(*GeV2Kelvin(np.array(ax1.get_xlim())))

ax2.set_xticks(Kelvin2GeV(locs))
ax2.set_xlim(ax1.get_xlim())

f = mticker.ScalarFormatter(useOffset=False, useMathText=True)
g = lambda x,pos : "${}$".format(f._formatSciNotation('%1.10e' % GeV2Kelvin(x)))
fmt = mticker.FuncFormatter(g)
ax2.xaxis.set_major_formatter(mticker.FuncFormatter(fmt))

plt.show()

ax2中的
ax1Xs
是什么。设置标签(勾选功能(ax1Xs))?