You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何sns.set与rcParams设置字体大小仅对suptitle生效?如何修复?

箱图字体大小修改失效问题

问题描述

尝试修改批量绘制的箱图中所有字体元素大小,但运行代码后仅图的总标题(suptitle)字体大小变化,其余坐标轴标签、刻度、子图标题等字体均无变化。代码如下:

from pathlib import Path
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt


def plot_group(df, nrow, ncol, size, plot_title):

    sns.set(style="darkgrid")
    plt.rcParams['font.size'] = size
    fig, axes = plt.subplots(nrow, ncol, figsize=(15, 10), tight_layout=True)
    fig.suptitle(plot_title)
    n_boxplots = 2
    for i in range(nrow):  
        for j in range(ncol): 
            current_ax = axes[i, j]
            sns.boxplot(data=df[['foo','bar']], palette="Set2", ax=current_ax)
            current_ax.set_title("foo", fontsize=18)

    plt.savefig(f'font_size_{size}.png', dpi=75)
    plt.close(fig)

nrow = 3
ncol = 3
rng = np.random.default_rng(0)
arr = rng.random((30, 2))
df = pd.DataFrame(data=arr, columns=['foo', 'bar'])
for size in [14, 22]:

    plot_title = f"Font size = {size}"
    plot_group(df, nrow, ncol, size, plot_title)

原因分析

  • Seaborn样式覆盖了rcParams设置:sns.set(style="darkgrid")会重置matplotlib的默认参数,包括字体相关配置,之后设置的plt.rcParams['font.size']会被Seaborn的样式参数覆盖,无法生效。
  • 子图标题硬编码固定大小:代码中current_ax.set_title("foo", fontsize=18)直接指定了固定的18号字体,不会随传入的size参数变化。
  • 部分字体元素需要单独指定参数:font.size是基础字体大小,但坐标轴标签、刻度等元素依赖于更具体的rcParams项(比如axes.labelsize、xtick.labelsize等),仅设置font.size无法覆盖所有元素。

修复方案

方案1:调整rcParams顺序+统一配置字体参数

把plt.rcParams设置放在sn.set()之后,补充全量字体相关rc参数,并去掉子图标题的硬编码字体大小:

from pathlib import Path
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt


def plot_group(df, nrow, ncol, size, plot_title):

    sns.set(style="darkgrid")
    # 统一设置所有字体相关的rc参数
    plt.rcParams.update({
        'font.size': size,
        'axes.labelsize': size,
        'axes.titlesize': size,
        'xtick.labelsize': size,
        'ytick.labelsize': size,
        'figure.titlesize': size  # 对应suptitle的大小
    })
    fig, axes = plt.subplots(nrow, ncol, figsize=(15, 10), tight_layout=True)
    fig.suptitle(plot_title)
    n_boxplots = 2
    for i in range(nrow):  
        for j in range(ncol): 
            current_ax = axes[i, j]
            sns.boxplot(data=df[['foo','bar']], palette="Set2", ax=current_ax)
            current_ax.set_title("foo")  # 不再硬编码fontsize,使用rcParams设置

    plt.savefig(f'font_size_{size}.png', dpi=75)
    plt.close(fig)

nrow = 3
ncol = 3
rng = np.random.default_rng(0)
arr = rng.random((30, 2))
df = pd.DataFrame(data=arr, columns=['foo', 'bar'])
for size in [14, 22]:
    plot_title = f"Font size = {size}"
    plot_group(df, nrow, ncol, size, plot_title)

方案2:使用Seaborn的set_context方法

Seaborn提供的set_context()可以便捷统一调整绘图元素大小,配合set_style()使用更符合Seaborn使用习惯:

from pathlib import Path
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt


def plot_group(df, nrow, ncol, size, plot_title):

    sns.set(style="darkgrid")
    # 使用set_context设置字体大小,base_fontsize对应基础字体大小
    sns.set_context("notebook", base_fontsize=size)
    fig, axes = plt.subplots(nrow, ncol, figsize=(15, 10), tight_layout=True)
    fig.suptitle(plot_title)
    n_boxplots = 2
    for i in range(nrow):  
        for j in range(ncol): 
            current_ax = axes[i, j]
            sns.boxplot(data=df[['foo','bar']], palette="Set2", ax=current_ax)
            current_ax.set_title("foo")  # 继承context中的字体大小

    plt.savefig(f'font_size_{size}.png', dpi=75)
    plt.close(fig)

nrow = 3
ncol = 3
rng = np.random.default_rng(0)
arr = rng.random((30, 2))
df = pd.DataFrame(data=arr, columns=['foo', 'bar'])
for size in [14, 22]:
    plot_title = f"Font size = {size}"
    plot_group(df, nrow, ncol, size, plot_title)

说明

两种方案都能实现所有字体元素随传入的size参数变化:

  • 方案1更灵活,可单独控制不同元素的字体大小;
  • 方案2设置更简洁,符合Seaborn的生态使用逻辑。

内容的提问来源于stack exchange,提问作者DeltaIV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:17:54