Matplotlib中解决X轴刻度标签重叠问题(需保留精确X轴数值)
我完全懂你的困扰——当X轴有两个极其接近的数值时,哪怕拉宽图表,标签还是挤在一起根本看不清,而且还不能随便改X轴的精确值,确实头疼。下面给你几个可行的办法,都能保留精确数值同时解决重叠问题:
办法1:错开重叠标签的垂直位置
如果只有个别标签重叠,最简单的方式就是把那两个重叠的标签上下错开,不用改X轴的布局。你只需要在设置plt.xticks之后,手动调整特定标签的垂直位置就行:
修改你的代码,在plt.xticks(xaxis, rotation=45, fontsize=8)这行后面加上这段:
# 获取X轴所有标签对象 xtick_labels = plt.gca().get_xticklabels() # 找到你那两个重叠的标签(对应x数组里的0.2192和0.2170,索引是1和2) xtick_labels[1].set_y(-0.08) # 第一个重叠标签往下移一点 xtick_labels[2].set_y(-0.15) # 第二个重叠标签再往下移一点 plt.subplots_adjust(bottom=0.2) # 增加图表底部空间,避免标签被切掉
这样两个标签一上一下就不会重叠了,其他标签位置不变,完全保留精确数值。
办法2:把X轴当作分类轴处理(强烈推荐)
如果想从根本上避免这种问题,而且接受X轴的刻度间距均匀分布(不用严格对应数值大小,毕竟那两个值太近了,视觉上几乎没区别),可以把X轴转成分类轴——每个数据点对应一个均匀分布的位置,标签保留原来的精确数值。
修改后的_plot函数代码如下:
import matplotlib.pyplot as plt import numpy as np def _plot(x, y, titel): # 用索引作为X轴的位置,让所有点均匀分布 x_indices = np.arange(len(x)) yaxis = np.array(y) x_np = np.array(x) # 拟合趋势线还是用原来的精确X数值,保证拟合结果准确 z = np.polyfit(x_np, yaxis, 1) p = np.poly1d(z) fit_y = p(x_np) print("\n\nFormel: y=%.6fx+%.6f"%(z[0],z[1])) print("Steigung von Trendlinie: {:.3f}".format(z[0])) # 绘图时用均匀分布的x_indices作为X轴位置 plt.scatter(x_indices, yaxis, marker='x', color='red', label='Werte') plt.plot(x_indices, fit_y, marker='x', color='black', mec='b', ls="--") plt.plot(x_indices, yaxis, color='#875252', ls=':') # 设置X轴刻度为索引,标签显示原来的精确数值 plt.xticks(x_indices, labels=[f"{val:.4f}" for val in x], rotation=45, fontsize=8) plt.tight_layout() plt.subplots_adjust(bottom=0.2) # 预留底部空间放标签 plt.xlabel('c(Pb²⁺) in mol/L') plt.ylabel(r"$\mathrm{pK}_{L}$") plt.legend(['gemessene Werte', 'Trendlinie / Linearer Fit']) plt.title(titel) plt.grid() plt.show()
这个方法的好处是:所有标签均匀排列,绝对不会重叠,而且每个标签都对应自己的数据点,趋势线的计算还是用原来的精确X数值,完全不影响分析结果。
办法3:增大图表宽度,给标签更多空间
如果不想改X轴逻辑,也可以直接把图表拉宽,让标签有足够的空间展示。只需要在函数开头添加一行设置图表尺寸的代码:
plt.figure(figsize=(10, 6)) # 宽度10,高度6,你可以根据需要调整
配合plt.tight_layout()和plt.subplots_adjust(bottom=0.2),大部分情况下也能缓解重叠问题,但如果两个值实在太近,可能还是会挤在一起,所以这个办法适合作为辅助手段。
你可以根据自己的需求选其中一个办法,我个人推荐办法2,既彻底解决重叠问题,又完全保留了所有精确数值的展示,对后续分析也没有影响。
备注:内容来源于stack exchange,提问作者leonarrrd

