代码语言

知识点思维导图

28 个知识节点

Python(22) - 数据可视化

读完后,你应能完成以下任务:

  • 绘制“Python(22) - 数据可视化 / 先建立前端锚点”的关键对象与数据流,解释“差别在于——ECharts 是"声明式塞一份 option",matplotlib 更像"命令式地往画布上一笔一笔画"。”,并用源码位置、日志或 Trace 标注证据。
  • 为“Python(22) - 数据可视化 / 最小可用:三行画一条折线”设计正常与异常输入,验证“记住这个对照:ECharts 是一份 option 对象,matplotlib 是一串 plt.xxx() 调用,最后 show() 等价于 ECharts 渲染到 DOM。”,输出首个偏差位置与回归测试结果。
  • 实现“Python(22) - 数据可视化 / 关键:matplotlib 有两套 API,别学混”的最小代码或配置,检验“新手看 matplotlib 教程最容易懵,是因为网上代码混用了两种写法。”,输出命令、结果与 Diff,并说明不适用边界。

你在前端画图,第一反应是 ECharts / Chart.js / D3:给个容器、塞一份 option 配置、它就渲染出图。Python 这边对标的就是 matplotlib——数据科学界事实上的"画图标准库",Pandas、NumPy 的结果几乎都靠它出图。本篇解决三个问题:怎么把一组数字快速画成折线/柱状/散点;matplotlib 那套"看起来很乱"的 API 到底分几种、该用哪种;以及在没有屏幕的后端服务器上怎么把图存成文件。

一、先建立前端锚点

你在前端这么做 matplotlib 对应 说明
import * as echarts from 'echarts' import matplotlib.pyplot as plt 引入画图库
echarts.init(dom) 拿到实例 fig, ax = plt.subplots() 拿到画布+坐标系 创建图
chart.setOption({...}) ax.plot(x, y) / ax.bar(...) 往图里塞数据
浏览器自动渲染到页面 plt.show()(弹窗)或 fig.savefig(...)(存文件) 输出
arr.map(...) 处理完数组再喂给图表 df.plot()(Pandas 直接出图) 数据→图一步到位

核心切入点:matplotlib ≈ 后端版的 ECharts/D3。差别在于——ECharts 是"声明式塞一份 option",matplotlib 更像"命令式地往画布上一笔一笔画"。理解了这个差异,后面那套看着零散的 API 就顺了。

安装:pip install matplotlib。它常和 NumPy(第 20 篇)、Pandas(第 21 篇)一起用,画图的数据来源通常就是它们。


二、最小可用:三行画一条折线

对照你熟悉的 ECharts,本质是同一件事,只是 matplotlib 把"配置"拆成了一行行函数调用:

// ECharts 等价写法:一份声明式 option 塞进去
chart.setOption({
  xAxis: { data: [1, 2, 3, 4, 5] },
  yAxis: {},
  series: [{ type: 'line', data: [2, 5, 3, 8, 7] }]
})

记住这个对照:ECharts 是一份 option 对象,matplotlib 是一串 plt.xxx() 调用,最后 show() 等价于 ECharts 渲染到 DOM。


三、关键:matplotlib 有两套 API,别学混

新手看 matplotlib 教程最容易懵,是因为网上代码混用了两种写法。务必先分清:

3.1 pyplot 状态机接口(plt.xxx)—— 像全局单例画布

plt.plot()plt.title() 这类直接挂在 plt 上的函数,背后操作的是一个全局"当前图"。你不用拿到任何对象,所有调用都默默作用在那块隐藏的画布上。

这种风格类比 JS 里操作一个全局 canvas 单例:你不传引用,函数内部自己找那块全局画布。写一次性脚本很爽,但多张图并存时容易画串。

3.2 面向对象接口(fig, ax)—— 像拿到 DOM 节点再操作

更推荐、也更可控的写法:先 plt.subplots() 拿到 fig(整张画布)和 ax(坐标系),之后所有操作都明确作用在 ax 上。

这就像前端里 const dom = document.getElementById('chart') 拿到节点再操作,而不是依赖某个全局状态。多子图、复杂布局、在函数里画图返回,一律用 OO 接口

状态机接口 OO 接口 类比
plt.plot(...) ax.plot(...) 全局 canvas vs 拿到的 DOM 节点
plt.title(...) ax.set_title(...) 注意 OO 多了 set_ 前缀
plt.xlabel(...) ax.set_xlabel(...) 同上
适合:一次性脚本、Jupyter 速画 适合:多图、库代码、可控布局 ——

边界提醒:两套 API 别在同一段代码里乱混。新手常见错误是先 fig, ax = plt.subplots() 又去调 plt.title(),结果标题加到了"当前图"而不是你的 ax 上,看着没生效。本篇之后统一用 OO 接口。


四、四种最常用的图

数据可视化 90% 的场景就这几种。下面都用 OO 接口。

4.1 折线图(趋势)—— ax.plot

4.2 柱状图(对比)—— ax.bar

4.3 散点图(相关性)—— ax.scatter

4.4 直方图(分布)—— ax.hist

直方图和柱状图不一样:柱状图是"每个分类一根柱",直方图是"把连续数据切成若干区间(bin),统计每段落了多少个",用来看分布。

图类型 函数 用来回答 ECharts 里的 type
折线 ax.plot 随时间怎么变 line
柱状 ax.bar 各类别谁高谁低 bar
散点 ax.scatter 两个量有无相关 scatter
直方 ax.hist 数据怎么分布 无直接对应,需自己分桶

五、常见定制:标题、坐标、图例、多线

一张图常常要画多条线、加网格、调范围。这些都是 ax 上的方法:

要点:多条线 = 在同一个 ax 上多次 plot,每条给不同 label,最后 ax.legend() 一次性显示图例。这和 ECharts 往 series 数组里塞多项是一个意思。


六、显示 vs 保存:后端服务器没有屏幕

这是前端转后端最容易踩的点。plt.show() 是要"弹窗"的,但你的代码常常跑在没有图形界面的服务器上(比如 FastAPI 接口里生成报表图)。这时候不能 show(),要直接存成文件。

6.1 保存为图片

注意:savefig 要在 show() 之前调用。因为 show() 在某些环境下会清空当前图,之后再 save 可能得到空白图。

6.2 无界面环境:切 Agg 后端

如果服务器连图形库都没装,import matplotlib.pyplot 可能直接报错或卡住。解决办法是在导入 pyplot 之前指定一个不依赖屏幕的后端 Agg

类比理解:浏览器里 ECharts 必须有 DOM 容器才能渲染;Agg 后端相当于给 matplotlib 一块"虚拟离屏 canvas",画完直接导出图片,全程不需要真实窗口。


七、和 Pandas 联动:一行出图

实际数据分析里,数据基本都在 Pandas 的 DataFrame 里(第 21 篇)。DataFrame 自带 .plot(),底层就是调 matplotlib,省去手动取列:

df.plot() 会自动把每一列画成一条线、用 index 当横轴、列名当图例——相当于帮你把"取数据 + 配 series"一步做完。快速探查数据时首选它。


八、绕不开的坑:中文显示成方块 □□□

这是中文用户用 matplotlib 的第一个拦路虎:标题、标签里的中文全变成空心方块。WHY:matplotlib 默认字体不含中文字形,找不到就用方块占位。解决办法是显式指定一个系统里有的中文字体:

plt.rcParams 是 matplotlib 的全局配置字典,类比前端的全局主题变量/CSS 变量——改一次,之后所有图都生效。


九、其他易踩的坑

  1. 两套 API 混用导致设置不生效(第三节已说,重复强调因为最常见)。拿了 ax 就一路 ax.set_xxx,别中途跳回 plt.title

  2. plt.show() 在脚本里会阻塞。它会卡住程序直到你手动关掉弹窗,循环里画多张图时尤其坑。批量出图请用 savefig 不用 show

  3. 忘了清理导致图越画越乱。状态机接口下连续画多张图,新图会叠在旧图上。要么每次用独立的 fig, ax = plt.subplots(),要么 plt.close(fig) 关掉上一张释放内存(服务器里循环出图不关会内存泄漏)。

  4. Jupyter 里不用 show() 也能显示。Notebook 环境自动渲染最后一个图对象,但写成 .py 脚本就必须 show()savefig(),别把 Jupyter 习惯带到脚本里。

  5. 直方图 hist 当成柱状图 barbar 要你自己给好每根柱的高度;hist 是给它一堆原始数据、它自己分桶统计。搞反了画出来不对。


十、总结

  • 先建立前端锚点:| 浏览器自动渲染到页面 | plt.show()(弹窗)或 fig.savefig(...)(存文件) | 输出 |
  • 最小可用:三行画一条折线:记住这个对照:ECharts 是一份 option 对象,matplotlib 是一串 plt.xxx() 调用,最后 show() 等价于 ECharts 渲染到 DOM。
  • 关键:matplotlib 有两套 API,别学混:新手看 matplotlib 教程最容易懵,是因为网上代码混用了两种写法。
  • 四种最常用的图:直方图和柱状图不一样:柱状图是"每个分类一根柱",直方图是"把连续数据切成若干区间(bin),统计每段落了多少个",用来看分布。
  • 常见定制:标题、坐标、图例、多线:这和 ECharts 往 series 数组里塞多项是一个意思。
  • 显示 vs 保存:后端服务器没有屏幕:这是前端转后端最容易踩的点。

学完自测

选择所有正确答案;提交后逐项核对判断依据。

1在“数据可视化”中,需要同时满足“先建立前端锚点”与“最小可用:三行画一条折线”。给定正文约束“matplotlib ≈ 后端版的 ECharts/D3。”,哪些判断保持了原有处理机制?多选
2“数据可视化”出现偏差:“在“数据可视化 / 关键:matplotlib 有两套 API,别学混”中,即使不满足“新手看 matplotlib 教程最容易懵,是因为网上代码混用了两种写法”,结果与副作用仍会保持不变。”已成为实际行为。围绕“关键:matplotlib 有两套 API,别学混”与“pyplot 状态机接口(plt.xxx)—— 像全局单例画布”,哪些判断能定位被改变的职责或边界?多选
3评审“数据可视化”方案时,验收条件包含“这就像前端里 const dom = document.getElementById('chart') 拿到节点再操作,而不是依赖某个全局状态。”。关于“面向对象接口(fig, ax)—— 像拿到 DOM 节点再操作”与“四种最常用的图”的哪些决策符合正文机制?多选