Matplotlib 3.2.1对数Y轴部分次要刻度标签缺失问题求助
解决Matplotlib 3.2.1中对数Y轴3倍次要刻度标签缺失的问题
问题背景
在Matplotlib 3.2.1版本中自定义对数Y轴的主次刻度标签,要求所有标签采用%g格式。当次要刻度设置为2、5的倍数时显示正常,但改为3的倍数后,0.3的标签缺失。相关修改后的代码片段如下:
minor_ticks = [0.003, 0.03, 0.3, 3, 30] minor_locator = ticker.LogLocator(base=10.0, subs=[0.3], numticks=12)
由于环境限制无法升级Matplotlib版本,需要找到兼容的解决方法。
原因分析
Matplotlib 3.2.1的LogLocator在生成subs=[0.3]对应的刻度时,会因浮点数精度问题生成近似值(例如0.30000000000000004),而原代码中使用val in minor_ticks的精确匹配会判定该值不在目标列表中,导致0.3的标签无法显示。
解决方案
以下两种方法均可解决该问题,无需升级Matplotlib版本:
方法一:使用模糊匹配替代精确判断
修改次要刻度的格式化函数,通过np.isclose()判断刻度值是否近似等于目标值,避免浮点数精度问题:
import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker as ticker N = 100 x = np.linspace(0, 1, N) np.random.seed(123) y = np.random.uniform(0.1, 50, N) fig, ax = plt.subplots() ax.plot(x, y) ax.set(yscale="log") # 主刻度设置 major_ticks = [0.001, 0.01, 0.1, 1, 10, 100] ax.set_yticks(major_ticks) ax.yaxis.set_major_formatter(ticker.FormatStrFormatter("%g")) # 次要刻度设置 minor_ticks = [0.003, 0.03, 0.3, 3, 30] minor_locator = ticker.LogLocator(base=10.0, subs=[0.3], numticks=12) def minor_tick_filter(val, pos): # 用极小误差范围匹配近似值 for tick_val in minor_ticks: if np.isclose(val, tick_val, rtol=1e-8): return '%g' % tick_val return '' ax.yaxis.set_minor_locator(minor_locator) ax.yaxis.set_minor_formatter(ticker.FuncFormatter(minor_tick_filter)) ax.set(xlim=[0, 1], ylim=[0.1, 100]) plt.minorticks_on() plt.show()
方法二:手动指定次要刻度位置
跳过LogLocator,直接通过ax.set_yticks()手动设置次要刻度的位置,避免自动生成的精度问题:
import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker as ticker N = 100 x = np.linspace(0, 1, N) np.random.seed(123) y = np.random.uniform(0.1, 50, N) fig, ax = plt.subplots() ax.plot(x, y) ax.set(yscale="log") # 主刻度设置 major_ticks = [0.001, 0.01, 0.1, 1, 10, 100] ax.set_yticks(major_ticks) ax.yaxis.set_major_formatter(ticker.FormatStrFormatter("%g")) # 次要刻度设置:直接指定位置 minor_ticks = [0.003, 0.03, 0.3, 3, 30] ax.set_yticks(minor_ticks, minor=True) ax.yaxis.set_minor_formatter(ticker.FormatStrFormatter("%g")) ax.set(xlim=[0, 1], ylim=[0.1, 100]) plt.minorticks_on() plt.show()
内容的提问来源于stack exchange,提问作者a11
相关产品推荐
相关产品推荐

