首页
/ Data Science for Beginners 第 11 课实战:用 Pandas 与 Matplotlib 以饼图、环形图、华夫图可视化蘑菇数据集的占比

Data Science for Beginners 第 11 课实战:用 Pandas 与 Matplotlib 以饼图、环形图、华夫图可视化蘑菇数据集的占比

2026-09-05 21:53:59作者:胡唯隽

本篇技术指南围绕数据科学入门课程第 11 课“Visualizing Proportions(可视化占比)”展开,基于仓库中的真实蘑菇数据集 data/mushrooms.csv,演示从全文本列的数据准备、groupby 分组统计,到用 Matplotlib 绘制饼图(Pie)、环形图(Donut)、用 PyWaffle 绘制华夫图(Waffle)的完整流程。读完后,你可以独立完成“按类别分组 → 计算占比 → 选择合适图表类型呈现比例”这一数据可视化的核心闭环。

饼图、环形图与华夫图:用蘑菇数据集可视化可食用/有毒比例

课程目标与数据集

本课的核心是学习三种“占比类”(proportions)图表:

  • 饼图(Pie chart)
  • 环形图(Donut chart)
  • 华夫图(Waffle chart)

配套课程说明见 课程 README,可交互练习在 课程 Notebook 中进行,参考答案在 solution/notebook.ipynb

课程使用的数据集来自 Audubon 的蘑菇清单详情,涵盖 23 种伞菌科(Agaricus)和 Lepiota 属的蘑菇。仓库中的 data/mushrooms.csv 实际包含 8124 条记录和 23 个字段,导入方式如下:

import pandas as pd
import matplotlib.pyplot as plt
mushrooms = pd.read_csv('../../data/mushrooms.csv')  # 相对于课程目录的路径
mushrooms.head()

23 个字段全部为文本型描述属性:

字段 含义示例
class 可食用性:Edible / Poisonous
cap-shapecap-surfacecap-color 菌盖形状、表面、颜色
bruisesodor 是否有淤伤、气味
gill-attachmentgill-spacinggill-sizegill-color 菌褶附着方式、间距、大小、颜色
stalk-shapestalk-rootstalk-surface-above/below-ringstalk-color-above/below-ring 菌柄形状、根部、环上下表面与颜色
veil-typeveil-color 菌幕类型与颜色
ring-numberring-type 菌环数量与类型
spore-print-color 孢子印颜色
population 生长密度:Abundant、Several、Scattered、Numerous 等
habitat 生境:Grasses、Leaves、Meadows、Paths、Urban、Waste、Wood

数据准备:把全文本列转换为 category 类型

观察前几行数据可以立即发现:整张表的数据全是文本,在绘制图表前必须先做类型转换。课程用 select_dtypes 验证了这一点:

print(mushrooms.select_dtypes(["object"]).columns)

输出显示 23 列全部为 object 类型(classcap-shapecap-surface……直到 habitat)。课程的做法是把所有 object 列统一转换为 category

cols = mushrooms.select_dtypes(["object"]).columns
mushrooms[cols] = mushrooms[cols].astype('category')

转换为 category 类型是 pandas 处理高基数/低基数文本列的标准手段:它降低内存占用,并让后续分组统计的语义更清晰。

转换后,按 class 分组计数即可得到占比分析的基础数据:

edibleclass = mushrooms.groupby(['class']).count()
edibleclass

分组结果与真实数据完全吻合:Edible 4208 条,Poisonous 3916 条(合计 8124 条),即可食用蘑菇略多于有毒蘑菇,比例约为 51.8% : 48.2%。

⚠️ 课程特别强调:后面构建图表 labels 数组时,顺序必须与分组结果中类别出现的顺序一致,否则标签和数据会错位。务必核对分组表的行序再写标签。

饼图(Pie):最直观的占比展示

直接用分组结果的 population 列绘制饼图:

labels = ['Edible', 'Poisonous']
plt.pie(edibleclass['population'], labels=labels, autopct='%.1f %%')
plt.title('Edible?')
plt.show()

各参数要点:

  • x 数据:edibleclass['population'],即按 class 分组后各列的计数(每个类别下所有非空计数相同,取哪一列都一样,取 population 仅为习惯);
  • labels:两个类别名,顺序对应分组结果;
  • autopct='%.1f %%':在每个扇区上自动标注百分比,保留 1 位小数;
  • plt.title('Edible?'):图表标题。

饼图结果:Edible 与 Poisonous 的比例

这张饼图直观展示了蘑菇数据集中两类蘑菇的比例分布。

环形图(Donut):饼图的“挖孔”变体

环形图本质上是中间留了个洞的饼图,视觉上更清爽,中心区域还能放汇总信息。课程用蘑菇的**生境(habitat)**字段来演示。

先按生境分组:

habitat = mushrooms.groupby(['habitat']).count()
habitat

分组后共 7 个生境类别,作为环形图的标签:

labels = ['Grasses', 'Leaves', 'Meadows', 'Paths', 'Urban', 'Waste', 'Wood']

plt.pie(habitat['class'], labels=labels,
        autopct='%1.1f%%', pctdistance=0.85)

center_circle = plt.Circle((0, 0), 0.40, fc='white')
fig = plt.gcf()

fig.gca().add_artist(center_circle)

plt.title('Mushroom Habitats')
plt.show()

关键实现细节:

  1. plt.pie 先画好完整饼图;
  2. plt.Circle((0, 0), 0.40, fc='white') 创建一个以原点为圆心、半径 0.40、白色填充的圆;
  3. fig.gca().add_artist(center_circle) 把这个圆叠加到当前坐标轴上,把饼图中心“盖住”,从而形成环形效果。

修改 0.40 这个半径值即可调整环的粗细——半径越大环越细,越小环越宽。pctdistance=0.85 控制百分比文字离圆心的距离(0 为中心、1 为边缘)。课程还提示可参考 Matplotlib 官方文档中关于饼图/环形图标签美化的示例来进一步提升可读性。

环形图结果:7 类生境的占比

对照 data/mushrooms.csv 的实际分布,各生境占比为:Wood 3148(约 38.7%)、Grasses 2148(26.4%)、Paths 1144(14.1%)、Leaves 832(10.2%)、Urban 368(4.5%)、Meadows 292(3.6%)、Waste 192(2.4%)——森林是绝对优势生境。

华夫图(Waffle):用 2D 方块数组表达数量比例

华夫图把数量按比例拆成网格中的小方块,是另一种“看占比”的方式。课程用蘑菇的**菌盖颜色(cap-color)**做演示,需要先安装辅助库 PyWaffle:

pip install pywaffle

先选出要分组的数据段:

capcolor = mushrooms.groupby(['cap-color']).count()
capcolor

菌盖颜色共 9 种,实际计数为:Brown 2284、Green 1856、Red 1500、Yellow 1072、White 1040、Buff 168、Pink 144、Cinnamon 44、Purple 16。构建华夫图:

import pandas as pd
import matplotlib.pyplot as plt
from pywaffle import Waffle

data = {'color': ['brown', 'buff', 'cinnamon', 'green', 'pink', 'purple', 'red', 'white', 'yellow'],
        'amount': capcolor['class']}

df = pd.DataFrame(data)

fig = plt.figure(
    FigureClass=Waffle,
    rows=100,
    values=df.amount,
    labels=list(df.color),
    figsize=(30, 30),
    colors=["brown", "tan", "maroon", "green", "pink", "purple", "red", "whitesmoke", "yellow"],
)

参数说明:

  • FigureClass=Waffle:让 Matplotlib 用 Waffle 类作为图形类渲染,而不是普通 Axes;
  • rows=100:网格共 100 行(配合内部自动推算列数),数值按总量等比铺满;
  • values=df.amount:各颜色类别的实际计数;
  • labels / colors:类别标签与对应颜色,两者顺序必须一一对应(brown→brown、buff→tan、white→whitesmoke 等);
  • figsize=(30, 30):正方形大画布,保证方块清晰。

华夫图结果:9 种菌盖颜色的数量占比

从图上可以一眼看出棕色(Brown)与绿色(Green)菌盖占绝对多数——课程也特别点出“绿盖蘑菇非常多”这一反直觉的发现。PyWaffle 还支持用 Font Awesome 图标替代方块,可以把华夫图做得更生动,值得自行实验。

如何选择:饼图、环形图还是华夫图

课程的 Review & Self Study 部分指出,三者何时使用并非总是显而易见,并给出了多篇对比文章供延伸阅读(饼图 vs 环形图的优劣对比、Waffle 图的正确用法等)。结合本课实践,可归纳为一条简单的选择逻辑:

图表 适用场景 注意点
饼图 2~6 个大类、强调“部分占整体” 类别太多会难以辨认;标签顺序必须与数据顺序一致
环形图 同饼图,但需要更现代的观感或中心放置标题/汇总 洞半径(如 0.40)决定环宽,pctdistance 控制百分比位置
华夫图 想让非专业读者用“数格子”的直觉感受数量比例 依赖 PyWaffle;适合总量可平铺成 100/1000 格的场景

三者共同的前提都是:先把数据 groupby 到目标类别上,统计出每类计数,再决定用哪种图呈现。这就是本课总结的核心工作流——“group → count → 选图 → 绘制”,读完这张图用户就能瞬间获得数据集的比例快照。

练习与延伸

  • 🚀 课程挑战:用 Microsoft Research 的 Charticulator(拖拽式数据可视化工具,其教程同样使用本蘑菇数据集)重绘本课图表;
  • 课后作业:assignment.md 要求在 Excel 中自选一份数据,制作饼图、环形图、华夫图三种图表,评分标准以图表数量分级(三个满分);
  • 动手验证:本课全部代码均可在 课程 Notebook 中逐步运行,完成后可与 solution/notebook.ipynb 中的实现逐 cell 对照,确认饼图、环形图、华夫图三种输出。
登录后查看全文
热门项目推荐
相关项目推荐