set_yticklabels()未清除旧刻度标签问题求助
问题原因分析
第三张图y轴出现两组刻度的核心原因是刻度设置逻辑与坐标轴含义不匹配,加上matplotlib自动刻度机制未被正确覆盖:
- 第三张图的ylabel是
$\log_{10} O_{lin}(k)$,说明y轴应展示取对数后的数值,但代码中yticks是通过logspace(min(logy), max(logy), 4)生成的——这是原始y值的对数空间刻度(即10^logy的原始数值),而非log10(y)的直接数值,导致自定义刻度和实际绘图数据的刻度范围不匹配,matplotlib自动补充了符合数据范围的刻度。 - 前两张图虽用了相同的logspace逻辑,但数据量级大,四舍五入转int后的刻度刚好覆盖自动刻度范围,因此未出现双重刻度。
解决方案
方法1:修正刻度逻辑(推荐)
既然ylabel是对数转换后的结果,直接基于logy生成线性刻度,匹配坐标轴含义:
for i, data in enumerate([pklin, psm, olin]): fig, ax = plt.subplots() x, y = data[0], data[1] ax.set_xlabel(r'$\log_{10}k [h $Mpc$^{-1}] $', fontsize=fontsize) logx = np.log10(x) logy = np.log10(y) # 绘制对数转换后的y值,匹配ylabel含义 ax.plot(x, logy) # x轴刻度:基于logx生成对数空间刻度,保留原显示逻辑 xticks = np.logspace(min(logx), max(logx), 4, base=10) ax.set_xticks(xticks) ax.set_xticklabels(np.round(xticks, 2), fontsize=fontsize) if i==0: # 基于logy生成线性刻度,匹配对数后的数值范围 yticks = np.linspace(np.floor(min(logy)), np.ceil(max(logy)), 4) yticks = [int(x) for x in yticks] ylabel = r'$\log_{10} P(k) [$Mpc$^3 h^{-3}]$' name = 'Pklin' print('First plot done!') elif i==1: yticks = np.linspace(np.floor(min(logy)), np.ceil(max(logy)), 4) yticks = [int(x) for x in yticks] ylabel = r'$\log_{10} P_{smooth}(k) [$Mpc$^3 h^{-3}]$' name = 'Psm' print('Second plot done!') elif i==2: yticks = np.linspace(np.floor(min(logy)), np.ceil(max(logy)), 4) yticks = np.round(yticks, 3) ylabel = r'$\log_{10} O_{lin}(k)$' name = 'Olin' print('Third plot done!') ax.set_yticks(yticks) ax.set_yticklabels(yticks, fontsize=fontsize) ax.set_ylabel(ylabel, fontsize=fontsize) plt.savefig(f'../figs/{name}.pdf')
方法2:禁用自动刻度(快速修复)
如果坚持原绘图逻辑(绘制原始y值),在设置yticks前禁用y轴自动缩放,强制使用自定义刻度:
# 在ax.set_yticks之前添加这行代码 ax.autoscale(enable=False, axis='y')
补充说明
- 原代码x轴存在冗余设置:先
ax.set_xticks((0.05, 1e-1, 0.45)),后又被ax.set_xticks(xticks)覆盖,建议删除第一行x轴刻度设置。 - 若要使用对数坐标轴展示原始y值,需添加
ax.set_yscale('log'),同时将ylabel修改为原始物理量(如$O_{lin}(k)$),此时logspace生成的yticks才是匹配的。
内容的提问来源于stack exchange,提问作者dolefeast
相关产品推荐
相关产品推荐

