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

如何在Matplotlib嵌套饼图中设置不同数量的子分类

解决Matplotlib嵌套饼图父类子分类数量自由设置的问题

原来的代码依赖二维numpy数组,要求每个父类的子分类数量必须一致,一旦子类数量不同就会触发AxisError。要实现自由设置各父类的子分类数量,核心是放弃二维numpy数组,改用普通列表的列表来存储数据,这样就能灵活处理不同长度的子分类,再分别计算父类总和、扁平化子类数据即可。

关键改动点:

  • 用普通列表的列表替代二维numpy数组存储各父类的子分类数值,允许子列表长度不同
  • 父类总和通过列表推导式计算:[sum(sub_vals) for sub_vals in vals]
  • 子类数据扁平化用嵌套列表推导式:[val for sublist in vals for val in sublist]
  • 对应调整子类标签、颜色的数量,匹配实际子分类个数

修改后的完整代码

import matplotlib.pyplot as plt
import numpy as np    

fig, ax = plt.subplots()

# 用列表的列表存储数据,允许各父类子分类数量不同
vals = [
    [60., 32., 13.],          # Car的3个子分类
    [37., 40., 45.],          # Public Transport的3个子分类
    [29., 10., 35., 15., 12.] # Bike的5个子分类(新增Tricycle、Unicycle)
]

cmap = plt.get_cmap("tab20c")
outer_colors = cmap(np.arange(3)*4)  # 3个父类对应3种颜色
# 11个子分类对应11种颜色(3+3+5),按父类分组选取
inner_colors = cmap([1,2,3, 5,6,7, 9,10,11,12,13])

# 绘制内圈(父类)
ax.pie(
    [sum(sub) for sub in vals],  # 计算每个父类的总和
    radius=3-0.9,
    colors=outer_colors,
    wedgeprops=dict(width=0.9, edgecolor='w'),
    labels=["Car","Public Transport","Bike"],
    pctdistance=1.1,
    labeldistance=0.65
)

# 绘制外圈(子类)
ax.pie(
    [val for sublist in vals for val in sublist],  # 扁平化子类数据
    radius=3,
    colors=inner_colors,
    wedgeprops=dict(width=0.9, edgecolor='w'),
    labels=["Gasoline","Diesel","Electric",
            "Bus","Tram","Train",
            "Normal Bike","E-Bike","Motorbike","Tricycle","Unicycle"],
    pctdistance=1.1,
    labeldistance=0.85
)

ax.set(aspect="equal", title='')
plt.show()

为什么原来的代码会报错?

原来的代码用np.array()创建二维数组,当子列表长度不一致时,numpy会生成dtype=object的数组,此时调用sum(axis=1)会触发AxisError——因为object类型数组不支持按轴求和。改用普通列表处理后,就能避开numpy的这个限制,完全自由设置各父类的子分类数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:12:50