🧐问题发现
在下述代码中,最后保存的图表,其"tittle"的中文无法正常显示
python
# 1. 导入模块
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 2. 设置图表显示风格
sns.set_style('whitegrid')
# 3. 读取数据
train_df = pd.read_csv('../../datasets/train.tsv', sep='\t')
dev_df = pd.read_csv('../../datasets/dev.tsv', sep='\t')
# 4. 绘制标签数量柱状图
sns.countplot(x='label', data=train_df)
plt.title('训练集标签数量柱状图')
plt.savefig('../../NLP_images/text_preprocessing_images/ch03_A_1.png')
plt.clf() # 清空当前图表
保存图表的效果如下:

😫尝试解决
我尝试使用添加下述代码解决上述问题:
python
# 1. 导入模块
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 显示中文字体和负号
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 2. 设置图表显示风格
sns.set_style('whitegrid')
# 3. 读取数据
train_df = pd.read_csv('../../datasets/train.tsv', sep='\t')
dev_df = pd.read_csv('../../datasets/dev.tsv', sep='\t')
# 4. 绘制标签数量柱状图
sns.countplot(x='label', data=train_df)
plt.title('训练集标签数量柱状图')
plt.savefig('../../NLP_images/text_preprocessing_images/ch03_A_1.png')
plt.clf() # 清空当前图表
但是无法解决上述问题。
【为什么呢?】
🙄问题根源
其核心原因:seaborn的图表显示风格设置覆盖了plt.rcParam的字体配置。
通过上述代码,可以发现我的 plt.rcParam 设置在 sns.set_style('whitegrid') 之前。在部分版本中,set_style('whitegrid') 或 set_theme 会重置Matplotlib 全局参数,刚好把我先前的 plt.rcParam 配置覆盖掉。
🤓解决方法
1. 调整代码的顺序
将 plt.rcParam的配置放到 sns.set_style() 之后,防止被覆盖!
python
# 1. 导入模块
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 2. 设置图表显示风格
sns.set_style('whitegrid')
# 显示中文字体和负号
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 3. 读取数据
train_df = pd.read_csv('../../datasets/train.tsv', sep='\t')
dev_df = pd.read_csv('../../datasets/dev.tsv', sep='\t')
# 4. 绘制标签数量柱状图
sns.countplot(x='label', data=train_df)
plt.title('训练集标签数量柱状图')
plt.savefig('../../NLP_images/text_preprocessing_images/ch03_A_1.png')
plt.clf() # 清空当前图表
2. 进阶排查(如果上述内容不生效)
可能是系统中没有 SimHei 该字体,可以使用下述代码查看系统中存在的可用字体:
python
from matplotlib import font_manager
# 打印出所有包含 'SimHei', 'Hei', 'YaHei', 'Song' 等关键字的字体名
zh_fonts = [f.name for f in font_manager.fontManager.ttflist if 'SimHei' in f.name or 'Hei' in f.name or 'YaHei' in f.name or 'Song' in f.name]
print("系统可用的中文字体有:", zh_fonts)
可以将终端打印的结果中的任意一种字体(如:'Microsoft YaHei')替换 plt.rcParam 中的 'SimHei' 。
3. 终极绝招:直接指定字体文件的绝对路径
如果上述两种方法都不奏效,可以去网上下载一个 'SimHei.ttf' 文件,并将它放到项目的统计目录下,通过绝对路径指定字体文件。
python
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 1. 将本地字体文件注册到 Matplotlib 的全局字体库中
font_path = 'SimHei.ttf' # 你的字体文件路径
font_manager.fontManager.addfont(font_path)
# 提取出注册后的字体名称(通常是 'SimHei')
font_name = font_manager.FontProperties(fname=font_path).get_name()
# 2. 全局设置字体和负号(只需设置这一次,后续所有图表都会自动生效)
plt.rcParams['font.sans-serif'] = [font_name]
plt.rcParams['axes.unicode_minus'] = False
# 3. 设置 Seaborn 风格(注意:一定要在设置完 plt.rcParams 之后调用,或者在 set_theme 中再次指定字体)
sns.set_theme(style="whitegrid", font=font_name)
# --- 接下来正常绘图,完全不需要再单独指定 fontproperties ---
sns.countplot(x='label', data=train_df)
plt.title('训练集标签数量柱状图') # 自动使用中文字体
plt.xlabel('标签') # 自动使用中文字体
plt.ylabel('数量') # 自动使用中文字体
plt.savefig('test.png')
😅小提醒
有时候 Matplotlib 会缓存字体列表 。如果你新安装了字体但依然不显示,可以尝试删除 Matplotlib 的缓存文件夹(通常在 C:\Users\你的用户名\.matplotlib 或 ~/.matplotlib 下),删除后重新运行代码,它会自动重建缓存。