第 十五 章 可视化入门:Matplotlib 做出像样的图

第 15 章 可视化入门:Matplotlib 做出像样的图

    • [15.1 本章你将学会什么](#15.1 本章你将学会什么)
    • [15.2 先讲清楚:Matplotlib 的正确心智模型](#15.2 先讲清楚:Matplotlib 的正确心智模型)
    • [15.3 数据准备:用一个"科研风格"的小数据集贯穿全章](#15.3 数据准备:用一个“科研风格”的小数据集贯穿全章)
    • [15.4 折线图:趋势展示(时间序列/实验过程)](#15.4 折线图:趋势展示(时间序列/实验过程))
    • [15.5 散点图:相关关系与离群点(最常用)](#15.5 散点图:相关关系与离群点(最常用))
    • [15.6 直方图:分布形态(正态性、偏态、峰度)](#15.6 直方图:分布形态(正态性、偏态、峰度))
    • [15.7 箱线图:组间差异 + 离群点(论文常用)](#15.7 箱线图:组间差异 + 离群点(论文常用))
    • [15.8 柱状图:均值对比(一定要加误差棒)](#15.8 柱状图:均值对比(一定要加误差棒))
    • [15.9 让图"像样"的 8 个细节(建议你形成模板)](#15.9 让图“像样”的 8 个细节(建议你形成模板))
    • [15.10 字体与中文:最常见的"图一出就崩"问题](#15.10 字体与中文:最常见的“图一出就崩”问题)
    • [15.11 导出:让你的图可以直接进论文(强烈建议用 PDF)](#15.11 导出:让你的图可以直接进论文(强烈建议用 PDF))
    • [15.12 本章练习(建议你真跑一遍)](#15.12 本章练习(建议你真跑一遍))
      • [练习 1:画一张"组间差异图"](#练习 1:画一张“组间差异图”)
      • [练习 2:画一张"相关图"](#练习 2:画一张“相关图”)
      • [练习 3:导出两种格式](#练习 3:导出两种格式)
    • [15.13 小结:你应该带走的"工程化结论"](#15.13 小结:你应该带走的“工程化结论”)
    • 下一章

做科研数据分析,画图不是"把数据画出来"这么简单。

一张像样的图,至少要做到三件事:信息表达清晰、统计含义正确、可在论文/报告中直接复用

这一章用 Matplotlib 走一遍从 0 到"能交付"的绘图流程:从最常用图型,到排版、字体、导出,再到科研场景常见坑的规避。


15.1 本章你将学会什么

  • Matplotlib 的基本对象模型:Figure / Axes(告别"画着画着失控")
  • 画出科研常用 6 类图:折线、散点、直方图、箱线图、柱状图、误差棒图
  • 让图"像样"的关键细节:标题、坐标轴、刻度、网格、注释、图例
  • 可复现导出:DPI、尺寸、矢量格式(PDF/SVG)、命名规范
  • 建立你自己的"科研绘图模板":一套代码贯穿整篇论文

15.2 先讲清楚:Matplotlib 的正确心智模型

很多初学者是这样画图的:

python 复制代码
import matplotlib.pyplot as plt
plt.plot([1,2,3],[4,5,6])
plt.show()

能画,但会遇到三个问题:

  1. 图一复杂就难控制
  2. 多图排版会乱
  3. 论文导出格式不稳定

推荐从一开始就用"面向对象(OO)写法"

python 复制代码
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(6, 4))
ax.plot([1,2,3], [4,5,6])
ax.set_title("Example")
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()

记住:
fig 管画布(整体),ax 管坐标系(具体图)。

你要控制排版、尺寸、导出,就必须把 fig/ax 拿在手里。


15.3 数据准备:用一个"科研风格"的小数据集贯穿全章

python 复制代码
import numpy as np
import pandas as pd

np.random.seed(42)

n = 120
df = pd.DataFrame({
    "sid": np.arange(1, n+1),
    "group": np.random.choice(["control", "treatment"], size=n),
    "age": np.random.normal(24, 2.5, size=n).round(1),
    "score": np.random.normal(80, 8, size=n).round(1)
})
df.head()

15.4 折线图:趋势展示(时间序列/实验过程)

折线图适用于:随时间、随试次变化的趋势。

python 复制代码
import matplotlib.pyplot as plt

t = np.arange(1, 11)
y = np.cumsum(np.random.normal(0, 1, size=10)) + 50

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(t, y, marker="o")
ax.set_title("Learning Curve (Example)")
ax.set_xlabel("Trial")
ax.set_ylabel("Score")
ax.grid(True, alpha=0.3)
plt.show()

科研建议

  • 趋势图必须有明确的横轴含义(时间、试次、阶段)
  • 不要用过多线条堆叠,容易造成"读不出来"

15.5 散点图:相关关系与离群点(最常用)

python 复制代码
fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(df["age"], df["score"], alpha=0.7)
ax.set_title("Age vs Score")
ax.set_xlabel("Age")
ax.set_ylabel("Score")
ax.grid(True, alpha=0.3)
plt.show()

你应该顺手做两件事

  1. 观察离群点(outliers)
  2. 初步判断是否线性关系(后续回归分析的直觉基础)

15.6 直方图:分布形态(正态性、偏态、峰度)

python 复制代码
fig, ax = plt.subplots(figsize=(6, 4))
ax.hist(df["score"], bins=15, alpha=0.8)
ax.set_title("Distribution of Score")
ax.set_xlabel("Score")
ax.set_ylabel("Count")
ax.grid(True, alpha=0.3)
plt.show()

科研建议

  • bins 不要拍脑袋:样本小用少 bins,样本大用多 bins
  • 直方图是"分布直觉",不是统计检验本身

15.7 箱线图:组间差异 + 离群点(论文常用)

python 复制代码
control = df[df["group"] == "control"]["score"]
treat = df[df["group"] == "treatment"]["score"]

fig, ax = plt.subplots(figsize=(6, 4))
ax.boxplot([control, treat], labels=["control", "treatment"])
ax.set_title("Score by Group (Boxplot)")
ax.set_ylabel("Score")
ax.grid(True, axis="y", alpha=0.3)
plt.show()

科研建议

  • 箱线图非常适合做"组间分布对比",而不是只展示均值
  • 论文里"只画柱状图"往往信息不足(容易被审稿人质疑)

15.8 柱状图:均值对比(一定要加误差棒)

柱状图在科研里最大的问题是:只画均值会误导

你至少要加上误差棒(标准差/标准误/置信区间),并说明是什么。

python 复制代码
summary = df.groupby("group")["score"].agg(["mean", "std", "count"])
summary["sem"] = summary["std"] / np.sqrt(summary["count"])
summary
python 复制代码
fig, ax = plt.subplots(figsize=(6, 4))

groups = summary.index.tolist()
means = summary["mean"].values
sems = summary["sem"].values

ax.bar(groups, means, yerr=sems, capsize=6, alpha=0.9)
ax.set_title("Mean Score by Group (with SEM)")
ax.set_ylabel("Score")
ax.grid(True, axis="y", alpha=0.3)
plt.show()

提醒:误差棒用 std 还是 sem,必须在图注或正文写清楚。


15.9 让图"像样"的 8 个细节(建议你形成模板)

你可以逐条对照检查:

  1. 标题是否描述了"图要说明什么",而不是"图是什么"
  2. 坐标轴是否标注单位(如 ms、%、cm、years)
  3. 刻度是否过密、是否需要旋转
  4. 是否加网格(轻微即可)帮助读数
  5. 图例是否遮挡数据点
  6. 是否标注关键点(峰值、异常、分界线)
  7. 是否控制留白(tight_layout)
  8. 导出是否满足投稿要求(DPI/矢量)

示例:统一排版

python 复制代码
fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(df["age"], df["score"], alpha=0.6)
ax.set_title("Age vs Score")
ax.set_xlabel("Age (years)")
ax.set_ylabel("Score")
ax.grid(True, alpha=0.25)
fig.tight_layout()
plt.show()

15.10 字体与中文:最常见的"图一出就崩"问题

科研场景里,中文最容易遇到:

  • 中文乱码
  • 负号显示为方块

在不同系统字体可用情况不同。推荐你在项目里写一个"尝试多字体"的小段:

python 复制代码
import matplotlib as mpl

mpl.rcParams["axes.unicode_minus"] = False
mpl.rcParams["font.sans-serif"] = ["Arial Unicode MS", "SimHei", "Microsoft YaHei"]

说明:不同机器字体库不同,这段的关键是"备选列表",提高可移植性。


15.11 导出:让你的图可以直接进论文(强烈建议用 PDF)

  • 论文图优先:pdf(矢量)或 svg
  • 网页展示:png(高 DPI)
python 复制代码
fig, ax = plt.subplots(figsize=(6, 4))
ax.hist(df["score"], bins=15, alpha=0.85)
ax.set_title("Score Distribution")
ax.set_xlabel("Score")
ax.set_ylabel("Count")
ax.grid(True, alpha=0.3)
fig.tight_layout()

fig.savefig("fig_score_distribution.png", dpi=300)
fig.savefig("fig_score_distribution.pdf")  # 矢量

命名建议(科研习惯)

  • fig_01_xxx.png/pdf
  • fig_02_xxx.png/pdf
  • 与论文图号一致,减少后期排版痛苦

15.12 本章练习(建议你真跑一遍)

练习 1:画一张"组间差异图"

要求:

  • 既包含分布信息(箱线图或散点抖动)
  • 又包含均值与误差棒(可叠加,或并排展示)

练习 2:画一张"相关图"

要求:

  • 散点图 + 标注 2 个离群点的 sid(用 ax.annotate

练习 3:导出两种格式

  • 导出 png(dpi=300)
  • 导出 pdf
    并检查二者在放大时的差异

15.13 小结:你应该带走的"工程化结论"

  • Matplotlib 的核心是 fig/ax,拿住它你才能稳定控制排版与导出
  • 科研图最怕"漂亮但不可信":柱状图必须配误差棒,分布最好直接展示
  • 做图要形成模板:标题、轴、刻度、网格、tight_layout、导出格式一套固定下来

下一章

《第16章 小项目2:CSV→清洗→统计→图表→报告输出》

相关推荐
爱喝可乐的老王1 天前
数据分析实践--数据解析购房关键
信息可视化·数据分析·pandas·matplotlib
渡我白衣7 天前
计算机组成原理(11):加法器
python·机器学习·numpy·pandas·matplotlib·计组·数电
老歌老听老掉牙8 天前
使用 Matplotlib 自定义坐标轴字体及刻度样式详解
python·matplotlib
AC赳赳老秦9 天前
DeepSeek教育科技应用:智能生成个性化学习规划与知识点拆解教程
前端·网络·数据库·人工智能·学习·matplotlib·deepseek
AC赳赳老秦11 天前
行业数据 benchmark 对比:DeepSeek上传数据生成竞品差距分析报告
开发语言·网络·人工智能·python·matplotlib·涛思数据·deepseek
2401_8414956412 天前
【Python高级编程】图着色动态可视化 APP
python·算法·matplotlib·tkinter·回溯法·图着色算法·动态可视化工具
laocooon52385788612 天前
对传入的 x , y 两个数组做折线图, x 对应 x 轴, y 对应 y 轴。并保存到 Task1/image1/T2.png
python·numpy·pandas·matplotlib
渡我白衣13 天前
Python 与数据科学工具链入门:NumPy、Pandas、Matplotlib 快速上手
人工智能·python·机器学习·自然语言处理·numpy·pandas·matplotlib
shenzhenNBA16 天前
python模块matplotlib绘图-饼图
python·matplotlib·pyplot·python绘制图表