Matplotlib:第二个轴上的 twinx() 值错误

2023-12-30

我遇到了一个问题plt.twinx()的函数matplotlib.pyplot当我尝试绘制主要的次要 x 轴时ln(x)-axis。它们应该显示相应的值,但具有不同的刻度。为了清楚起见,这是我迄今为止在 MWE 中尝试过的:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator

fig = plt.figure(1)
ax1 = fig.add_subplot(111)

ax1.set_xlabel(r'$ln(\sigma)$')
ax1.set_xticks([5.2,5.3,5.4,5.5,5.6,5.7,5.8])
ax1.set_xlim([5.2,5.8])
ax1.plot(5.6,0.5,'o')

ax2 = ax1.twiny()
ax2.set_xlabel(r'$\sigma$')
ax2.set_xlim(np.exp(ax1.get_xlim()))
ax2.xaxis.set_major_locator(MultipleLocator(base=25))

plt.show()

这会产生以下图,乍一看似乎符合预期,但存在问题,即辅助 x 刻度是错误的。

次要 x 值错误的绘图 https://i.stack.imgur.com/TM0EU.png

该点位于x1 = 0.5但相应的次要 x 值位于x2 =~ 280但毕竟应该是在x2 = math.exp(5.6) =~ 270

我不太确定这是一个绘图问题还是一个具有不同尺度的更深层次的数学问题。

当我没有设置时它会起作用ax2.xlim()但只需将主要 x 刻度加倍并使用matplotlib.ticker.FuncFormatter将辅助 x 刻度格式化为np.exp(ax1.get_xticlocs())但随后辅助刻度处于“奇怪”值。


这是出了什么问题

这是因为两个 x 尺度之间的映射是非线性的(指数/对数)。实际上,您有一个轴作为对数刻度,另一个轴作为正常刻度。根据您定义限制的方式,两者在端点处重合,但不在两者之间重合。下面演示了这个想法。 x2 的“映射值”相对于 x1 值绘制在 y 轴上。我标记为“仅限端点”的蓝线是您所期望的,但“全域”映射是现实中发生的情况。

import matplotlib.pyplot as plt
import numpy as np

# Endpoints only
x01 = np.array([5.2,5.8])
y01 = np.exp(x01)

# Full domain
x = np.linspace(5.2,5.8,100)
y = np.exp(x)

plt.plot(x01,y01,label='endpoints only')
plt.plot(x,y, label='full domain')
plt.legend()
plt.show()

这是一种解决方法

在对数刻度上实例化两个轴。在你的情况下你想要自然对数,所以我们通过basex=np.e。然后,您需要手动指定两个轴上的刻度位置。在ax1我们只使用预先指定的位置;为了ax2您可以使用指定后生成的位置MultipleLocator.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.set_xscale('log', basex=np.e)

# Array of tick locations...use the true value (not log value)
locs = np.exp(np.array([5.2,5.3,5.4,5.5,5.6,5.7,5.8]))

ax1.set_xlabel(r'$ln(\sigma)$')
ax1.set_xlim([locs[0],locs[-1]])
ax1.set_xticks(locs)
ax1.set_xticklabels(np.log(locs))

ax2 = ax1.twiny()
ax2.set_xscale('log', basex=np.e)
ax2.set_xlabel(r'$\sigma$')
ax2.set_xlim((ax1.get_xlim()))
ax2.xaxis.set_major_locator(MultipleLocator(base=25))
# Manually set the tick labels to match the positions your set with the locator
ax2.set_xticklabels(['{:.0f}'.format(k) for k in ax2.get_xticks()])  

ax1.plot(locs,locs*0+.4,'o')
ax2.plot(locs,locs*0+.6,'o',color='C1')
ax1.set_ylim([0,1])

plt.show()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Matplotlib:第二个轴上的 twinx() 值错误 的相关文章

随机推荐