查看全课大纲(第 38 / 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 如何快速统计元素出现次数?

Matplotlib 绘图的第一步该做什么?

约 7 分钟

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

从本章开始,我们将进入 Python 数据可视化的学习。数据可视化是数据分析中不可或缺的一环,它能将枯燥的数据转化为直观的图形,帮助我们快速发现规律。本节课是数据可视化章节的第一课,我们将学习 Python 中最常用的绘图库 Matplotlib 的基本使用方法,为后续绘制各类图表打下基础。

💡 核心导读

  • 认识 Matplotlib:了解 Matplotlib 是什么,以及它能绘制哪些常见图形。
  • 第一个绘图程序:掌握使用 Matplotlib 绘制图形的标准流程:准备数据 -> 调用绘图函数 -> 显示图形。
  • 理解数据输入:学会如何为 plt.plot() 函数提供 x 和 y 坐标数据,无论是列表还是 NumPy 数组。
  • 数组与列表的差异:初步了解 NumPy 数组(ndarray)在数值计算上的便利性,特别是它“对每个元素执行相同运算”的特点。

Matplotlib 是什么?

Matplotlib 是 Python 中一个强大的绘图工具包。它的核心优势在于,使用者只需几行简单的代码,就能根据数据生成高质量的图表。

Matplotlib 几乎支持所有在数据分析中常用的图形,例如:

  • 折线图:展示数据随时间或其他连续变量的变化趋势。
  • 直方图:展示数据的分布情况。
  • 散点图:展示两个变量之间的关系。
  • 饼图:展示各部分占整体的比例。
  • 柱形图:对比不同类别的数据。

在接下来的课程中,我们会逐一学习这些图形的绘制方法。本节课,我们先从一个最简单的例子开始,感受 Matplotlib 的基本用法。

第一个绘图程序:绘制直线

使用 Matplotlib 绘图,我们主要用到其子模块 pyplot。它把常用的绘图操作封装成了几个简单的函数,调用起来非常直观。

一个完整的绘图流程通常包含以下三步:

  1. 导入模块:导入 matplotlib.pyplot,并习惯上简写为 plt。
  2. 准备数据:准备好要绘制的 x 坐标和 y 坐标数据。
  3. 绘图与显示:调用 plt.plot() 把数据画到当前的 Figure(画板)上;在本地有图形界面的环境中,再调用显示函数 show 把图形呈现出来。

下面我们通过绘制一条直线 y = 2x + 1 来实践这个流程。为了生成平滑的直线,我们需要在 x 轴上取一系列等间距的点。这里我们会用到 NumPy 库的 linspace 函数来生成这些点。

import matplotlib
matplotlib.use("Agg")  # 使用无图形界面后端,保证在服务器/CI 中也能运行
import matplotlib.pyplot as plt
import numpy as np

# 1. 准备数据:使用 NumPy 的 linspace 函数生成 0 到 10 之间等间距的 50 个点,作为 x 坐标
x = np.linspace(0, 10, 50)
print("x的前五个值:", x[:5])

# 2. 计算 y 坐标:y = 2*x + 1
# 注意:这里的乘法对 NumPy 数组中的每个元素分别进行计算
y = 2 * x + 1
print("y的前五个值:", y[:5])

# 3. 绘图:先创建一个图形窗口(5英寸 x 5英寸),再绘制 x 和 y 的关系图
plt.figure(figsize=(5, 5))
plt.plot(x, y)
print("图形已绘制(一条直线)。")
x的前五个值: [0.         0.20408163 0.40816327 0.6122449  0.81632653]
y的前五个值: [1.         1.40816327 1.81632653 2.2244898  2.63265306]
图形已绘制(一条直线)。

代码解读:

  • np.linspace(0, 10, 50):在 0 到 10 的区间内,生成 50 个等间距的数。
  • y = 2 * x + 1:这行代码体现了 NumPy 数组的强大之处。x 是一个包含 50 个元素的数组,这行代码会自动对数组中的每一个元素都执行 2 * 元素值 + 1 的操作,结果生成一个新的、同样包含 50 个元素的数组 y。
  • plt.figure(figsize=(5,5)):可选步骤,用于设置图形窗口的大小(单位:英寸)。
  • plt.plot(x, y):这是绘图的核心函数。它接收 x 坐标数组和 y 坐标数组,并将这些点按顺序用线段连接起来。因为我们提供了 50 个密集的点,所以画出来就是一条平滑的直线。
  • 显示函数 show:在本地带图形界面的环境里,它会把图形窗口显示出来。注意:在无图形界面的服务器环境里,这个函数可能报错或无反应;本讲义统一使用 Agg 后端,因此不调用显示函数,图形对象仍会正常生成。

用列表直接绘图

plt.plot() 函数非常灵活,它不仅能接受 NumPy 数组,也能直接接受 Python 原生的列表(list)作为输入。

当我们只想绘制少数几个点之间的连线时,直接使用列表会更加方便。

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

# 第一张图:绘制两个点 (0, 10) 和 (1, 20) 之间的连线
plt.figure()
plt.plot([0, 1], [10, 20])
print("图形已绘制(两个点之间的线段)。")

# 第二张图:绘制三个点 (0,10), (-2,3), (1,20) 之间的连线
plt.figure()  # 新建一张图,避免和上一张叠加
plt.plot([0, -2, 1], [10, 3, 20])
print("图形已绘制(三个点连接成的折线)。")
plt.close("all")
图形已绘制(两个点之间的线段)。
图形已绘制(三个点连接成的折线)。

原理:plt.plot([0, 1], [10, 20]) 意味着:

  • 第一个点的坐标是 (x=0, y=10)
  • 第二个点的坐标是 (x=1, y=20) Matplotlib 会在这两个点之间画一条直线。

如果我们传入更多的点,Matplotlib 会依次用直线将所有点连接起来。

这里,点 (0,10) 和 (-2,3) 之间会连一条线,(-2,3) 和 (1,20) 之间会连另一条线,最终形成一条折线。

绘制曲线与 NumPy 数组的优势

现在我们来绘制一条曲线,例如 y = x²。同样,我们需要先生成一系列 x 值,再计算对应的 y 值。

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

# 生成 x 数据:0 到 10 之间的 50 个等分点
x = np.linspace(0, 10, 50)
print("x的前三个值:", x[:3])

# 计算 y = x²
# 这是 NumPy 数组的逐元素运算:对数组中每个元素求平方
y = x ** 2
print("y的前三个值:", y[:3])

# 绘图
plt.plot(x, y)
print("图形已绘制(抛物线 y = x²)。")
x的前三个值: [0.         0.20408163 0.40816327]
y的前三个值: [0.         0.04164931 0.16659725]
图形已绘制(抛物线 y = x²)。

这里再次体现了 NumPy 数组“对每个元素执行相同运算”的特点:x ** 2 会对 x 数组中的每一个元素进行平方运算。

为什么用 NumPy 数组而不是普通列表?

让我们对比一下 NumPy 数组和 Python 列表在数值计算上的行为差异:

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

# 使用 NumPy 数组
np_array = np.array([1, 2, 3])
result_np = np_array * 2  # 对每个元素乘以2
print("NumPy 数组乘以2:", result_np)

# 使用 Python 列表
py_list = [1, 2, 3]
result_list = py_list * 2  # 将列表重复2次
print("Python 列表乘以2:", result_list)
NumPy 数组乘以2: [2 4 6]
Python 列表乘以2: [1, 2, 3, 1, 2, 3]

可以看到:

  • NumPy 数组:* 2 是数学上的“逐元素乘法”,符合我们做数值计算时的直觉。
  • Python 列表:* 2 是“重复操作”,将列表内容复制一遍并拼接。

因此,在进行科学计算和绘图时,使用 NumPy 数组会更加方便。不过请放心,plt.plot() 函数两者都支持。

📝 动手练一练

  1. 尝试修改第一个例子中的直线方程,将 y = 2*x + 1 改为 y = -0.5*x + 3,并重新运行代码,观察绘制出的直线有何变化。
  2. 不借助 NumPy,仅使用 Python 列表,如何绘制出 y = x² 在 x 取值 [0, 1, 2, 3, 4] 时的图像?(提示:你需要手动计算每个 x 对应的 y 值,形成两个列表。)
👉 点击查看参考答案

思路:

  1. 修改计算公式即可改变直线。
  2. 手动计算平方值,构造 x_list 和 y_list,然后传入 plt.plot。

参考代码:

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

# 练习1:绘制 y = -0.5*x + 3
x = np.linspace(0, 10, 50)
y = -0.5 * x + 3  # 修改了这里
plt.figure()
plt.plot(x, y)
print("练习1图形已绘制(斜向下的直线)。")

# 练习2:用列表绘制 y = x² (x=0,1,2,3,4)
x_list = [0, 1, 2, 3, 4]
y_list = [0, 1, 4, 9, 16]  # 手动计算平方值
plt.figure()  # 新建一个图形,避免和上一个叠加
plt.plot(x_list, y_list)
print("练习2图形已绘制(五个点连接的抛物线轮廓)。")
plt.close("all")
练习1图形已绘制(斜向下的直线)。
练习2图形已绘制(五个点连接的抛物线轮廓)。

常见错误

错误写法现象或报错原因正确写法
绘图后忘记调用显示函数代码运行无报错,但看不到图形窗口弹出。plt.plot() 只是把内容画到当前 Figure 上,本地脚本还需要调用显示函数(show)才会弹出窗口。在本地环境中于绘图命令后调用显示函数 show。
将 Python 列表的“重复”操作误认为是“逐元素计算”期望得到 [2, 4, 6],实际得到 [1, 2, 3, 1, 2, 3]。Python 列表的 * 运算符是重复,不是数学乘法。NumPy 数组的 * 才是逐元素乘法。使用 NumPy 数组:np.array([1,2,3]) * 2,或使用列表推导式:[i*2 for i in [1,2,3]]。
import matplotlib 后直接使用 plotNameError: name 'plot' is not definedplot 函数位于 matplotlib.pyplot 子模块中,通常的导入方式是 import matplotlib.pyplot as plt。import matplotlib.pyplot as plt
plt.plot(…)
在无图形界面的环境中调用显示函数 show程序可能卡住、报错或无任何输出。显示函数依赖图形前端。服务器等无界面环境需要配置非交互式后端。在导入 pyplot 前设置 matplotlib.use("Agg"),并去掉显示调用。

小结

  1. Matplotlib 是 Python 的核心绘图库,通过其 pyplot 模块可以轻松创建各类图表。
  2. 绘图的基本流程是:导入模块 (import matplotlib.pyplot as plt) -> 准备数据 (x, y) -> 调用绘图函数 (plt.plot(x, y)) -> 显示图形(本地环境调用显示函数 show)。
  3. plt.plot() 函数接收两个序列(列表或数组)作为参数,分别代表点的 x 坐标和 y 坐标,并将点按顺序用直线连接。
  4. 使用 NumPy 数组 (ndarray) 准备数据非常方便,它可以对整个数组的每个元素执行相同的数学运算。
  5. Python 原生列表也可以直接用于绘图,但其元素级数学运算的语法与 NumPy 数组不同,需要注意区分。

📋 行动清单

  • 在本地 Python 环境中运行本节课的第一个示例代码,确认打印的 x、y 前几个值正确、图形对象成功生成。
  • 尝试修改 np.linspace(0, 10, 50) 中的参数,比如将 50 改为 5 或 100,重新运行并观察绘制出的直线有何不同(是更粗糙还是更平滑?)。
  • 动手完成“练一练”中的两个练习,体会修改公式和手动构造数据的过程。

—— 小象教研组

配套资料 · 直接下载

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

  • 第5章代码包:Matplotlib的简单例子(含1 个 Notebook)
    ZIP · 706B
    下载