查看全课大纲(第 42 / 51 节)
  1. 1.Python 是什么?为什么值得学?
  2. 2.如何为 Python 编程准备一个“全家桶”环境?
  3. 3.Python 有哪几种执行方法?
  4. 4.行与缩进到底有什么用?
  5. 5.注释有什么用,怎么写?
  6. 6.变量:如何给数据起个好名字?
  7. 7.运算符的优先级和常见坑点是什么?
  8. 8.Python 中,数字和布尔值究竟有哪几种?
  9. 9.输入函数 `input()` 和文件读取 `open()` 怎么用?
  10. 10.如何将程序的结果展示给用户或保存下来?
  11. 11.CSV 文件怎么读怎么写才方便?
  12. 12.列表是什么,如何创建和访问它?
  13. 13.列表的修改操作,有哪些方法?
  14. 14.列表切片为什么能取到部分元素?排序和查找又该怎么用?
  15. 15.判断语句:如何让程序根据条件做不同的事?
  16. 16.for 循环如何遍历序列中的元素?
  17. 17.while 循环什么时候才会停?
  18. 18.while 循环的结束条件,你写对了吗?
  19. 19.循环中途想提前结束,怎么办?
  20. 20.`break` 和 `continue` 到底有什么区别?
  21. 21.列表推导式如何让代码更简洁高效?
  22. 22.字符串怎么定义、拼接和操作?
  23. 23.元组:为什么定义单个元素时要加逗号?
  24. 24.集合(set)怎么用?如何快速去重和做集合运算?
  25. 25.字典是什么,为什么比列表更方便?
  26. 26.字典的增删改查与遍历,如何避免 KeyError?
  27. 27.函数里的变量,为什么有的能用有的不能用?
  28. 28.在函数内部修改全局变量,为什么有时不生效?
  29. 29.函数里能修改全局变量吗?返回值怎么用?
  30. 30.匿名函数:如何用 lambda 快速定义简单函数?
  31. 31.面向对象编程是什么,为什么需要它?
  32. 32.类中的方法和属性到底怎么定义和使用?
  33. 33.如何控制对对象内部属性和方法的访问?
  34. 34.异常发生时,程序会怎样继续执行?
  35. 35.如何组织代码:包和模块
  36. 36.`if __name__ == '__main__'` 到底有什么用?
  37. 37.如何用 IDE 的 Debug 功能排查程序错误?
  38. 38.Matplotlib 绘图的第一步该做什么?
  39. 39.Figure 是什么,如何设置图形尺寸?
  40. 40.如何自定义 Matplotlib 的坐标轴?
  41. 41.如何为图表添加图例,让不同曲线一目了然?
  42. 42.饼图怎么画才能直观展示数据占比?
  43. 43.如何用 Matplotlib 绘制散点图?
  44. 44.柱状图怎么画?
  45. 45.如何使用 Matplotlib 绘制等高线图?
  46. 46.如何在 Matplotlib 中绘制子图?
  47. 47.zip 函数如何把多个列表“打包”在一起?
  48. 48.如何给可迭代对象加上索引?
  49. 49.random 模块如何生成随机数?
  50. 50.math 模块怎么用?
  51. 51.Counter 如何快速统计元素出现次数?

饼图怎么画才能直观展示数据占比?

约 5 分钟

小象实战讲义 · Python 编程从入门到实践

这一节,我们学习使用 Matplotlib 库中的 pie() 函数来绘制饼图。饼图是一种直观展示数据各部分占总和百分比的图表。学完本节,你将能绘制一个基础的饼图,并能通过参数调整其样式,如突出某一部分、添加标签和阴影等。本节是第5章《数据可视化》的第5节,你需要先了解如何用 Matplotlib 绘制曲线、设置坐标轴和图例,后续我们将学习更多图表类型。

💡 核心导读

  • 饼图的作用:直观展示一个数据集合中,各个分量所占的百分比。
  • 核心函数:plt.pie(),其关键参数包括 sizes(各部分大小)、labels(标签)、explode(突出显示)和 autopct(百分比格式)。
  • 绘制方向:饼图各部分默认按逆时针方向绘制,起始角度由 startangle 参数控制。
  • 图形形状:默认绘制为椭圆,使用 plt.axis('equal') 可确保绘制为正圆。
  • 常见调整:通过 shadow 参数添加阴影,通过修改 sizes 列表自动重算百分比。

绘制一个最简单的饼图

饼图通过 matplotlib.pyplot.pie() 函数绘制。最核心的参数是 sizes,它是一个列表,定义了饼图每一部分的大小。

import matplotlib
matplotlib.use("Agg")  # 使用非交互式后端,确保代码在无图形界面环境下也能运行
import matplotlib.pyplot as plt

# 定义各部分的大小
sizes = [15, 30, 45, 10]

# 绘制饼图
plt.pie(sizes)
plt.axis('equal')  # 确保绘制的是正圆
plt.close()  # 关闭图形,释放资源
print("已绘制一个包含4部分的饼图,各部分大小分别为:", sizes)
已绘制一个包含4部分的饼图,各部分大小分别为: [15, 30, 45, 10]

plt.pie(sizes) 会根据 sizes 列表中每个数值占总和的比例,自动计算出该部分在饼图中应占的扇形角度。列表内数值的总和不一定非得是100,Matplotlib 会自动进行比例换算。

为饼图添加标签与样式

一个完整的饼图通常需要标签、百分比显示以及一些视觉增强效果。

  • labels: 一个元组或列表,用于定义每一部分对应的文本标签。
  • explode: 一个长度与 sizes 相同的元组或列表,用于指定某一部分“突出”显示的距离。数值为0表示不突出,大于0(如0.1)则表示将该部分从圆心向外拉出一段距离。
  • autopct: 一个格式化字符串,用于控制饼图内部显示的百分比数值的格式。例如 '%1.1f%%' 表示保留一位小数的百分比。
  • shadow: 布尔值(True 或 False),决定是否为饼图添加阴影效果。
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

# 定义数据
labels = ('Frogs', 'Hogs', 'Dogs', 'Logs')  # 各部分标签
sizes = [15, 30, 45, 10]                    # 各部分大小
explode = (0, 0.1, 0, 0)                    # 突出显示第二个部分('Hogs')

# 绘制带样式和标签的饼图
plt.pie(sizes,
        explode=explode,
        labels=labels,
        autopct='%1.1f%%',  # 显示百分比,保留一位小数
        shadow=True)        # 添加阴影
plt.axis('equal')
plt.close()
print("饼图已绘制,包含标签:{}。其中 '{}' 部分被突出显示。".format(labels, labels[1]))
饼图已绘制,包含标签:('Frogs', 'Hogs', 'Dogs', 'Logs')。其中 'Hogs' 部分被突出显示。

控制起始角度与图形比例

饼图的绘制还有一些细节可以调整,以满足不同的展示需求。

  • startangle: 定义绘制第一个部分(对应 sizes[0] 和 labels[0])的起始角度。0度指向图形右侧(3点钟方向),90度指向正上方(12点钟方向)。绘制方向为逆时针。
  • plt.axis('equal'): 这个语句不属于 plt.pie() 的参数,而是需要在绘图后单独调用。它确保x轴和y轴的单位长度相等,从而将默认的椭圆饼图变为正圆。如果省略,图形可能会被拉伸。
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

labels = ('Frogs', 'Hogs', 'Dogs', 'Logs')
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0)

# 从90度(正上方)开始绘制,并确保是正圆
plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
        shadow=True, startangle=90)
plt.axis('equal')  # 关键:确保绘制的是正圆,而不是椭圆
plt.close()
print("饼图已从90度(正上方)开始逆时针绘制,并确保为正圆形。")
饼图已从90度(正上方)开始逆时针绘制,并确保为正圆形。

如果不加 plt.axis('equal'),图形可能会呈现椭圆形,这在某些情况下可能不符合展示要求。

📝 动手练一练

假设一次班级投票中,四种水果的得票数分别为:苹果20票、香蕉15票、橙子10票、草莓5票。请绘制一个饼图来展示投票结果,要求:

  1. 为每个部分添加正确的水果名称标签。
  2. 突出显示得票最少的“草莓”部分。
  3. 百分比显示保留一位小数。
  4. 确保饼图是正圆。
👉 点击查看参考答案

思路:根据题目要求准备数据。sizes 列表对应票数,labels 列表对应水果名。要突出显示“草莓”(列表最后一个元素),需在 explode 元组对应位置设置一个大于0的值(如0.1)。最后调用 plt.pie() 并设置 autopct 和 plt.axis('equal')。

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

# 1. 定义数据
fruits = ['苹果', '香蕉', '橙子', '草莓']
votes = [20, 15, 10, 5]
# 2. 突出显示最后一个部分(草莓)
highlight = (0, 0, 0, 0.1)

plt.pie(votes, labels=fruits, explode=highlight, autopct='%1.1f%%', startangle=0)
plt.axis('equal')
plt.close()
print("班级水果喜好投票饼图已绘制。总票数:{}。{}被突出显示。".format(sum(votes), fruits[-1]))
班级水果喜好投票饼图已绘制。总票数:50。草莓被突出显示。

常见错误

错误写法现象或报错原因正确写法
省略 plt.axis('equal')饼图显示为椭圆形,不是正圆。Matplotlib 默认的坐标轴比例不一致,导致图形被拉伸。在 plt.pie() 后加上 plt.axis('equal')。
explode = (0.1)TypeError: object of type 'float' has no len()括号里只有一个数时,(0.1) 只是浮点数,不是元组;explode 需要与 sizes 等长的可迭代对象。explode = (0.1, 0, 0, 0);只有一个部分时写成 (0.1,)。
autopct='%1f%%'百分比显示为类似 15.000000% 的格式,小数位过多。格式字符串 '%1f' 只指定了总宽度,没有指定小数位数,因此沿用默认的 6 位小数。autopct='%1.1f%%'(显示一位小数)或 autopct='%1.0f%%'(不显示小数)。
认为 sizes 总和必须是100误以为列表数字直接代表百分比。sizes 中的数值代表原始大小,Matplotlib 会自动计算比例。总和为任意正数即可。理解 sizes = [15, 30, 45, 10] 与 sizes = [150, 300, 450, 100] 会画出比例相同的饼图。

小结

  1. 使用 plt.pie(sizes) 可以绘制最基本的饼图,sizes 列表定义了各部分的大小。
  2. labels 参数为各部分添加文本标签,autopct 参数控制饼图内部百分比的显示格式。
  3. explode 参数可以突出显示饼图的特定部分,通过给对应位置一个大于0的值实现。
  4. shadow=True 可以为饼图添加阴影效果,增强立体感。
  5. startangle 参数决定了饼图第一个部分绘制的起始角度(0度为右侧,逆时针绘制)。
  6. 务必在绘图后调用 plt.axis('equal'),以确保饼图显示为正圆形,而非默认的椭圆形。

📋 行动清单

  • 运行一遍示例代码,观察 explode 参数不同取值对图形的影响。
  • 修改 sizes 列表中的数值,使其总和不为100,观察饼图百分比的变化。
  • 尝试将 startangle 分别设置为 0、90、180,理解起始角度与绘制方向的关系。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第5章代码包:饼图(含1 个 Notebook)
    ZIP · 744B
    下载