Matplotlib:更改数学字体大小后恢复默认设置

7 投票
3 回答
7670 浏览
提问于 2025-04-17 23:21

我从这个问题 Matplotlib: Change math font size 学到了如何在 matplotlib 中改变数学文本的默认大小。我所做的是:

from matplotlib import rcParams
rcParams['mathtext.default'] = 'regular'

这样做的效果是让LaTeX字体和普通字体的大小一样。

但我不知道怎么把这个设置恢复到默认状态,也就是让LaTeX字体看起来比普通字体小一点。

我需要这样做是因为我只想在一个图上让LaTeX字体和普通字体看起来一样大,而不是在我图中所有使用LaTeX数学格式的图上都这样。

下面是我创建图的一个 MWE 示例:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.gridspec as gridspec

# Generate random data.
x = np.random.randn(60)
y = np.random.randn(60)

fig = plt.figure(figsize=(5, 10))  # create the top-level container
gs = gridspec.GridSpec(6, 4)  # create a GridSpec object

ax0 = plt.subplot(gs[0:2, 0:4])
plt.scatter(x, y, s=20, label='aaa$_{subaaa}$')
handles, labels = ax0.get_legend_handles_labels()
ax0.legend(handles, labels, loc='upper right', numpoints=1, fontsize=14)
plt.ylabel('A$_y$', fontsize=16)
plt.xlabel('A$_x$', fontsize=16)

ax1 = plt.subplot(gs[2:4, 0:4])
# I want equal sized LaTeX fonts only on this plot.
from matplotlib import rcParams
rcParams['mathtext.default'] = 'regular'

plt.scatter(x, y, s=20, label='bbb$_{subbbb}$')
handles, labels = ax1.get_legend_handles_labels()
ax1.legend(handles, labels, loc='upper right', numpoints=1, fontsize=14)
plt.ylabel('B$_y$', fontsize=16)
plt.xlabel('B$_x$', fontsize=16)

# If I set either option below the line that sets the LaTeX font as 'regular'
# is overruled in the entire plot.
#rcParams['mathtext.default'] = 'it'
#plt.rcdefaults()

ax2 = plt.subplot(gs[4:6, 0:4])
plt.scatter(x, y, s=20, label='ccc$_{subccc}$')
handles, labels = ax2.get_legend_handles_labels()
ax2.legend(handles, labels, loc='upper right', numpoints=1, fontsize=14)
plt.ylabel('C$_y$', fontsize=16)
plt.xlabel('C$_x$', fontsize=16)

fig.tight_layout()

out_png = 'test_fig.png'
plt.savefig(out_png, dpi=150)
plt.close()

3 个回答

1

这里有一个很棒的Python方法,可以临时改变rcParams(配置参数),而且在用完后会自动恢复。首先,我们定义一个上下文管理器,这样就可以和with一起使用:

from contextlib import contextmanager

@contextmanager
def temp_rcParams(params):
    backup = {key:plt.rcParams[key] for key in params}  # Backup old rcParams
    plt.rcParams.update(params) # Change rcParams as desired by user
    try:
        yield None
    finally:
        plt.rcParams.update(backup) # Restore previous rcParams

接着,我们可以用这个上下文管理器来临时改变某个特定图表的rcParams

with temp_rcParams({'text.usetex': True, 'mathtext.default': 'regular'}):
    plt.figure()
    plt.plot([1,2,3,4], [1,4,9,16])
    plt.show()

# Another plot with unchanged options here
plt.figure()
plt.plot([1,2,3,4], [1,4,9,16])
plt.show()

结果:

两个不同字体的示例图表

2

另一种解决方案是更改rcParams设置,强制matplotlib在所有文本中使用tex。我对这个设置的理解不深,所以不打算详细解释。简单来说,就是通过设置

mpl.rcParams['text.usetex']=True

你可以将字符串传递给任何(或者大部分?)文本定义的函数,这些字符串会被传递给tex,这样你就可以使用它的大部分“黑科技”。在这种情况下,只需要使用\tiny\small\normalsize\large\Large\LARGE\huge\Huge这些字体大小命令就可以了。

在你的MWE例子中,只需将第二行散点图改为

plt.scatter(x, y, s=20, label=r'bbb{\Huge$_{subbbb}$}')

就可以在图例中获得更大的下标字体。其他情况都会被正确处理。

4

我觉得这是因为 mathtext.default 这个设置是在绘制坐标轴对象的时候使用的,而不是在创建它的时候。为了绕过这个问题,我们需要在坐标轴对象绘制之前改变这个设置,下面是一个演示:

# your plot code here

def wrap_rcparams(f, params):
    def _f(*args, **kw):
        backup = {key:plt.rcParams[key] for key in params}
        plt.rcParams.update(params)
        f(*args, **kw)
        plt.rcParams.update(backup)
    return _f

plt.rcParams['mathtext.default'] = 'it'
ax1.draw = wrap_rcparams(ax1.draw, {"mathtext.default":'regular'})

# save the figure here

这是输出结果:

enter image description here

撰写回答