Matplotlib文献风格轴科学计数法:如何修改默认字体?
解决Matplotlib双坐标轴特定字体的文献风格科学计数法问题
问题背景
已通过自定义MathTextSciFormatter实现文献风格的科学计数法坐标轴标签,但无法通过plt.xticks(font="Arial")或tick.set_fontname("Arial")修改字体(仅字号可调),使用版本为Matplotlib 3.5.3。
问题原因
自定义Formatter返回的是LaTeX数学模式字符串(用$...$包裹),Matplotlib会使用数学字体渲染这类内容,普通的tick标签字体设置不会作用于数学模式文本。
解决方案
方法1:全局配置数学文本字体
通过修改Matplotlib的rc参数,指定数学模式下使用目标字体(如Arial),适用于全局所有数学文本:
修改代码开头,添加以下配置:
import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker as mticker # 配置数学文本使用Arial字体 plt.rcParams['mathtext.fontset'] = 'custom' plt.rcParams['mathtext.rm'] = 'Arial' plt.rcParams['mathtext.it'] = 'Arial:italic' plt.rcParams['mathtext.bf'] = 'Arial:bold' # 后续原代码保持不变 fig,ax=plt.subplots(1,1,figsize=[7,7]) x=np.linspace(0,0.1,10**3) y=x**2 ax.plot(x,y) # 原自定义Formatter代码 class MathTextSciFormatter(mticker.Formatter): def __init__(self, fmt="%1.2e"): self.fmt = fmt def __call__(self, x, pos=None): s = self.fmt % x decimal_point = '.' positive_sign = '+' tup = s.split('e') significand = tup[0].rstrip(decimal_point) sign = tup[1][0].replace(positive_sign, '') exponent = tup[1][1:].lstrip('0') if exponent: exponent = '10^{%s%s}' % (sign, exponent) if significand and exponent: s = r'%s{\times}%s' % (significand, exponent) else: s = r'%s%s' % (significand, exponent) return "${}$".format(s) plt.gca().xaxis.set_major_formatter(MathTextSciFormatter("%1.2e")) plt.gca().yaxis.set_major_formatter(MathTextSciFormatter("%1.2e")) plt.xticks(rotation=45, font="Arial", fontsize=20) for tick in ax.get_yticklabels(): tick.set_fontname("Arial")
方法2:在Formatter中强制使用文本字体
修改自定义MathTextSciFormatter的返回逻辑,将有效数字部分用\mathrm{}包裹,强制使用文本字体:
import numpy as np import matplotlib.pyplot as plt import matplotlib.ticker as mticker fig,ax=plt.subplots(1,1,figsize=[7,7]) x=np.linspace(0,0.1,10**3) y=x**2 ax.plot(x,y) # 修改后的自定义Formatter class MathTextSciFormatter(mticker.Formatter): def __init__(self, fmt="%1.2e"): self.fmt = fmt def __call__(self, x, pos=None): s = self.fmt % x decimal_point = '.' positive_sign = '+' tup = s.split('e') significand = tup[0].rstrip(decimal_point) # 用\mathrm{}包裹有效数字,强制使用文本字体 significand = r'\mathrm{%s}' % significand sign = tup[1][0].replace(positive_sign, '') exponent = tup[1][1:].lstrip('0') if exponent: exponent = '10^{%s%s}' % (sign, exponent) if significand and exponent: s = r'%s{\times}%s' % (significand, exponent) else: s = r'%s%s' % (significand, exponent) return "${}$".format(s) plt.gca().xaxis.set_major_formatter(MathTextSciFormatter("%1.2e")) plt.gca().yaxis.set_major_formatter(MathTextSciFormatter("%1.2e")) # 字体设置生效 plt.xticks(rotation=45, font="Arial", fontsize=20) for tick in ax.get_yticklabels(): tick.set_fontname("Arial") tick.set_fontsize(20)
验证说明
两种方法均可让坐标轴的科学计数法标签使用Arial字体,方法1适合全局统一配置,方法2更灵活,可针对特定Formatter单独设置。
内容的提问来源于stack exchange,提问作者vrvn
相关产品推荐
相关产品推荐

