当我尝试为主要plt.twinx()
绘制辅助x轴时,我遇到了matplotlib.pyplot
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-ticks是错误的。
plot with wrong secondary x-values
该点位于x1 = 0.5
,但相应的辅助x值位于x2 =~ 280
,但毕竟应位于x2 = math.exp(5.6) =~ 270
我不确定这是一个绘图问题还是一个不同尺度的深度数学问题。
当我没有设置ax2.xlim()
但只是将主要x-tick加倍并使用matplotlib.ticker.FuncFormatter
将辅助x-tick格式化为np.exp(ax1.get_xticlocs())
时,它可以正常工作次要蜱是奇怪的"值。
答案 0 :(得分:1)
这是因为两个x标度之间的映射是非线性的(它是指数/对数)。实际上,您将一个轴作为对数刻度,另一个轴作为正常刻度。根据您如何定义限制,两者在端点上重合,但不在两者之间。这个想法如下所示。 "映射值"在y轴上绘制x2与x1值的关系。我标记的蓝线"仅端点"是你所期望的,但是"完整的域名"映射是现实中发生的事情。
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()