使用对数刻度时Matplotlib次坐标轴出现反转问题
Matplotlib次坐标轴对数刻度反转问题
我在使用对数刻度绘制次坐标轴时遇到了反转问题:
- 将星等(magnitude)设为主坐标轴(左侧),范围设为
10→0(星等越小代表亮度越高) - 光度(luminosity)设为次坐标轴(右侧),光度越高对应星等越小,前两幅图表现正常
- 但为光度设置对数刻度后,次坐标轴出现反转,光度随星等增大而上升,不符合物理逻辑
代码示例
# Test secondary axis import numpy as np import matplotlib import matplotlib.pyplot as plt print(matplotlib.__version__) # Mag to luminosity (solar units) conversion M_sun = 4.83 def mag2lum(mag): return 10**(0.4*(M_sun - mag)) def lum2mag(L): return M_sun - 2.5*np.log10(L) def mag2lgl(mag): return 0.4*(M_sun - mag) def lgl2mag(lgl): return M_sun - 2.5*lgl # log luminosity as second axis - correct behaviour fig, ax = plt.subplots(constrained_layout=True) plt.ylabel(r'$M_G$ [mag]') plt.xlim(-1, 5) plt.ylim(10, 0) secax = ax.secondary_yaxis('right', functions=(mag2lgl, lgl2mag)) secax.set_ylabel(r'$\log\ L_G\ [L_\odot]$') plt.show() # luminosity as second axis - correct behaviour, but labelling is horrible fig, ax = plt.subplots(constrained_layout=True) plt.ylabel(r'$M_G$ [mag]') plt.xlim(-1, 5) plt.ylim(10, 0) secax = ax.secondary_yaxis('right', functions=(mag2lum, lum2mag)) secax.set_ylabel(r'$L_G\ [L_\odot]$') plt.show() # luminosity as second axis on log scale: axis is reversed fig, ax = plt.subplots(constrained_layout=True) plt.ylabel(r'$M_G$ [mag]') plt.xlim(-1, 5) plt.ylim(10, 0) secax = ax.secondary_yaxis('right', functions=(mag2lum, lum2mag)) secax.set_ylabel(r'$L_G\ [L_\odot]$') secax.set_yscale('log') plt.show()
问题原因
这不是Matplotlib的Bug,而是主坐标轴处于反转状态(ylim(10,0)),设置次坐标轴对数刻度时,Matplotlib默认应用对数轴的常规方向(数值从小到大),打破了和主轴的反转对应关系,导致刻度方向不符合物理逻辑。
解决方法
方法1:手动反转次坐标轴
在设置对数刻度后,手动反转次轴方向,匹配主轴的物理意义:
# 修复后的对数光度次坐标轴代码 fig, ax = plt.subplots(constrained_layout=True) plt.ylabel(r'$M_G$ [mag]') plt.xlim(-1, 5) plt.ylim(10, 0) secax = ax.secondary_yaxis('right', functions=(mag2lum, lum2mag)) secax.set_ylabel(r'$L_G\ [L_\odot]$') secax.set_yscale('log') # 手动反转次坐标轴,让光度随星等减小(向上)递增 secax.invert_yaxis() plt.show()
方法2:直接使用对数光度转换函数
复用第一幅图的对数光度转换逻辑,避免额外处理刻度方向,逻辑更清晰:
# 更简洁的对数光度次坐标轴实现 fig, ax = plt.subplots(constrained_layout=True) plt.ylabel(r'$M_G$ [mag]') plt.xlim(-1, 5) plt.ylim(10, 0) secax = ax.secondary_yaxis('right', functions=(mag2lgl, lgl2mag)) secax.set_ylabel(r'$\log\ L_G\ [L_\odot]$') plt.show()
内容的提问来源于stack exchange,提问作者Jon Loveday
相关产品推荐
相关产品推荐

