Python画饼图怎么显示中文标签和百分比
在Python中使用Matplotlib绘制饼图时,中文标签常出现方块乱码且默认不显示百分比。本文介绍如何通过配置rcParams中文字体以及利用autopct参数快速实现中文标签与精确百分比的完整显示方法。
plt.pie() 绘制饼图时,实现中文标签正常显示的核心是修改全局字体配置 plt.rcParams['font.sans-serif'] 指定系统存在的中文字体,并同步设置 plt.rcParams['axes.unicode_minus'] = False;而在扇区上显示百分比的核心是启用 autopct 参数,通过传入格式化字符串(如 '%1.1f%%')或自定义回调函数自动完成弧度占比换算与文本渲染。
一、为什么默认绘制时中文显示为方块且没有百分比
很多初学者在首次调用 plt.pie(data, labels=labels) 时,会发现图表上的中文全部变成了空心方块(豆腐块),同时饼图的各个扇区上没有任何占比数值。理解这两个现象的底层成因,有助于准确排除环境差异带来的干扰。
首先是中文字体缺失问题。Matplotlib 默认的无衬线字体为 DejaVu Sans,该字体库只收录了西方字符编码,内部完全没有 CJK(中日韩)汉字的矢量字形表。当图表引擎尝试渲染传入的中文标签时,在字符映射表(cmap)中找不到对应 Unicode 码点的字形数据,便只能使用默认的缺省方块进行替代,并在终端输出 Glyph missing 警告。
其次是百分比显示机制。在 plt.pie() 内部,数值列表仅用于计算各扇区的圆心角弧度,百分比文本并不是默认生成的视觉元素。如果不显式为参数 autopct 赋值,其缺省值为 None,渲染流程便会跳过百分比文本对象的实例化阶段,因此图中仅保留纯色扇区与外部标签。
二、核心操作步骤:从字体配置到百分比输出
要规范且稳定地生成包含中文和百分比的饼图,可以遵循以下 4 个标准化步骤展开:
- 配置系统支持的中文字体:在导入
matplotlib.pyplot之后、调用任何绘图函数之前,优先设置plt.rcParams['font.sans-serif']。建议提供一个包含多种主流字体的列表,以便脚本在 Windows、macOS 与 Linux 间流转时能够自动回退。 - 准备并校验业务数据:构建数值序列
values与对应的标签序列labels。两个列表的元素个数必须严格相等,且数据通常应为非负数。 - 调用 pie() 并指定核心参数:将数据和标签传入函数,同时为
autopct传入格式化控制字符串(如'%1.1f%%'代表保留一位小数)。 - 保持正圆比例并输出展示:调用
plt.axis('equal')确保饼图在不同窗口尺寸下均保持正圆而非椭圆,最后调用plt.show()或plt.savefig()导出图片。
三、完整可运行代码示例
下面是一份完整的端到端 Python 脚本,涵盖了跨平台字体定义、基础数据构造、百分比格式化以及基础美化参数。读者可直接在本地 Python 环境中执行:
import matplotlib.pyplot as plt
# 1. 解决中文显示与负号异常
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'PingFang SC', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
# 2. 准备业务数据与中文标签
categories = ['线上电商', '线下门店', '企业直销', '渠道分销', '海外代销']
sales_data = [42.5, 28.0, 15.3, 9.2, 5.0]
# 突出显示占比最大的扇区(可选)
explode_settings = (0.05, 0, 0, 0, 0)
# 定义扇区配色方案(保持简洁柔和)
slice_colors = ['#6487A5', '#C28B68', '#7E9E8D', '#D4A373', '#A0AEC0']
# 3. 绘制饼图并配置核心参数
plt.figure(figsize=(7, 7))
patches, texts, autotexts = plt.pie(
sales_data,
labels=categories,
autopct='%1.1f%%', # 核心:显示百分比并保留一位小数
pctdistance=0.68, # 百分比数字距离圆心的距离(半径比例)
labeldistance=1.12, # 中文标签距离圆心的距离
startangle=90, # 起始角度:从正上方(90度)开始逆时针绘制
explode=explode_settings, # 扇区分离距离
colors=slice_colors,
textprops={'fontsize': 12, 'color': '#2D3748'} # 外部中文标签样式
)
# 4. 微调百分比文本外观
for autotext in autotexts:
autotext.set_color('white') # 百分比文字设为白色
autotext.set_fontsize(11) # 字号略小于标签
autotext.set_weight('bold') # 加粗提升辨识度
# 5. 确保正圆比例并设置标题
plt.title('2026年度业务销售渠道占比分析', fontsize=15, pad=18, fontweight='bold')
plt.axis('equal')
plt.tight_layout()
# 6. 展示图表
plt.show()
四、关键几何与位置参数深度解析
在实际业务图表中,单纯显示出百分比往往不够,经常会出现文字与扇区重叠、数值挤在圆心附近或标签被裁切的情况。深入理解以下几个控制位置的参数,能够让排版更协调:
1. autopct 格式串与自定义函数
autopct 能够接受两种形式的输入:
- Python 原生格式化字符串:例如
'%d%%'或'%1.0f%%'输出无小数点的整数百分比;'%1.1f%%'输出 1 位小数;'%1.2f%%'输出 2 位小数。注意最后的双百分号%%用于转义输出真实的%字符。 - 自定义回调函数:当需要在扇区内同时展示“百分比”和“原始绝对值”时,可传入自定义函数。
autopct会将计算出的百分比数值(0~100 之间的浮点数)作为参数传递给该函数。
# 自定义回调函数:同时输出百分比与具体数值
def make_autopct(values):
def my_autopct(pct):
total = sum(values)
val = int(round(pct * total / 100.0))
return f'{pct:.1f}%\n({val}万元)'
return my_autopct
# 调用方式
plt.pie(sales_data, labels=categories, autopct=make_autopct(sales_data))
2. pctdistance 与 labeldistance 的比例关系
饼图在 Matplotlib 内部以单位圆(半径 $R = 1.0$)为基准建立坐标系:
pctdistance(默认值 0.6):表示百分比文字锚点到圆心的欧氏距离与圆半径的比值。当扇区数量多且较窄时,可将该值调至 0.7~0.8,使数字向外扩散避免与圆心堆叠。labeldistance(默认值 1.1):表示外部类别中文标签距离圆心的比值。若设为大于 1 的值,标签置于扇区外侧;若设为小于 1(例如 0.5),标签则会绘制在扇区内部。
五、跨平台字体对照与常见问题排查
在不同操作系统或无桌面环境(如云端服务器、Docker 容器)中运行代码时,最容易出现字体失效或标签遮挡问题。以下是排查路线与应对措施:
| 操作系统 | 首选内置中文字体名 | 备选字体名 | 说明 |
|---|---|---|---|
| Windows | SimHei(黑体) |
Microsoft YaHei(微软雅黑) |
Win 7 及以上系统均自带,兼容性最佳 |
| macOS | PingFang SC(苹方) |
Arial Unicode MS / Heiti SC |
现代 macOS 系统自带,排版质感出众 |
| Linux / Ubuntu | Noto Sans CJK SC |
WenQuanYi Micro Hei |
通常需通过 apt install fonts-noto-cjk 预先安装 |
如果确认系统中已安装了中文字体,但 Matplotlib 依然提示
findfont: Generic family 'sans-serif' not found,通常是因为 Matplotlib 在首次启动时生成的本地字体缓存文件未更新。此时只需找到缓存目录(通常在 ~/.matplotlib/fontlist-*.json)并将其删除,重启 Python 进程后即可自动重新扫描并识别新字体。
备用方案:使用 FontProperties 显式指定本地字体文件
在企业生产环境或权限受限的服务器中,若无法修改系统全局字体或无权更新系统字体库,可以使用 matplotlib.font_manager.FontProperties 直接指向本地项目目录下的 .ttf 或 .otf 字体文件,免去对全局 rcParams 的依赖:
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
# 显式加载本地指定的字体文件
my_font = FontProperties(fname='/path/to/fonts/SourceHanSansCN-Regular.otf', size=12)
# 在 pie 中传递给 textprops
plt.pie(
[30, 70],
labels=['已完成', '未完成'],
autopct='%1.1f%%',
textprops={'fontproperties': my_font}
)
plt.title('进度概览', fontproperties=my_font, fontsize=14)
plt.show()
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









