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

如何在Matplotlib饼图中按组explode多块扇区?

Matplotlib饼图实现按组拆分(Explode in Groups)功能

我非常喜欢Matplotlib饼图的explode选项,希望实现**按组拆分(explode in groups)**功能——绘制多个分属3-4个类别的小扇区,将同一类别的所有小扇区作为整体拆分出来。

数据格式与现有代码

# 数据格式示例
axis1    
Unix    A     3
        B     1
        D     1
Window  C    30
Apple   A     1
        D    12
Linux   A    10
        C    20 

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
ax.set_aspect('equal')
labels=["{0} {1}".format(l1, l2) for l1, l2 in data.index]
wedges, texts, percs = ax.pie(data, labels=labels, autopct='%1.1f%%', shadow=True, radius=3)
ax.axes.get_yaxis().set_visible(False)

尝试的代码及报错

我尝试了以下代码:

groups = ["{0}".format(l1, l2) for l1, l2 in data.index]

for i in groups:
    ang = np.deg2rad((wedges[i[-1]].theta2 + wedges[i[0]].theta2)/2)

出现错误:"list indices must be integers or slices, not str"

期望效果:同一类别的扇区整体向外突出显示(类似分组拆分的饼图)


问题原因

wedges是Matplotlib返回的楔形对象列表,只能用整数索引访问,用字符串i去索引自然会报错。要实现按组拆分,核心是先给每个类别(比如A/B/C/D)分配对应的拆分距离,生成explode数组后传给pie函数。

解决方案代码

基础实现:按类别拆分

先整理数据,给目标类别的所有扇区设置拆分距离:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 把数据转为多层索引的DataFrame
data = pd.DataFrame(
    [['Unix', 'A', 3],
     ['Unix', 'B', 1],
     ['Unix', 'D', 1],
     ['Window', 'C', 30],
     ['Apple', 'A', 1],
     ['Apple', 'D', 12],
     ['Linux', 'A', 10],
     ['Linux', 'C', 20]],
    columns=['OS', 'Category', 'Value']
).set_index(['OS', 'Category'])

fig, ax = plt.subplots()
ax.set_aspect('equal')

# 提取每个扇区对应的类别
categories = [idx[1] for idx in data.index]
# 定义拆分规则:比如让A、D类别的扇区向外拆分0.1,其他类别不拆分
explode = [0.1 if cat in ['A', 'D'] else 0 for cat in categories]

labels = ["{0} {1}".format(l1, l2) for l1, l2 in data.index]
wedges, texts, percs = ax.pie(
    data['Value'], 
    labels=labels, 
    autopct='%1.1f%%',
    shadow=True, 
    radius=3,
    explode=explode  # 传入拆分数组
)

ax.axes.get_yaxis().set_visible(False)
plt.show()

进阶优化:同一类别统一拆分方向

如果希望同一类别的所有扇区向同一个方向拆分(更贴合“整体拆分”的视觉效果),可以额外调整楔形的中心偏移:

# 按类别分组,记录每个类别对应的扇区索引
category_indices = {}
for idx, cat in enumerate(categories):
    if cat not in category_indices:
        category_indices[cat] = []
    category_indices[cat].append(idx)

# 对目标类别的扇区统一调整拆分方向
for cat, indices in category_indices.items():
    if cat in ['A', 'D']:
        # 计算该类别所有扇区的平均角度
        avg_angle = np.mean([(wedges[i].theta1 + wedges[i].theta2)/2 for i in indices])
        angle_rad = np.deg2rad(avg_angle)
        # 按平均角度计算偏移量
        explode_dist = 0.1
        offset_x = np.cos(angle_rad) * explode_dist
        offset_y = np.sin(angle_rad) * explode_dist
        # 逐个调整扇区的中心位置
        for i in indices:
            wedges[i].set_center((offset_x, offset_y))

这样就能实现同一类别所有扇区作为整体向外拆分的效果,和期望的一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:27:20