Matplotlib 基础
学习目标
- 理解 Figure 和 Axes 的对象模型
- 掌握 5 种基本图表的绑制
- 学会定制图表元素(标题、图例、网格等)
- 掌握子图布局
为什么要学可视化?
"一图胜千言。"
同样的数据——
- 用表格展示:
平均薪资: 技术部 18667, 市场部 19000, 管理部 32500 - 用图表展示:一眼就能看出管理部薪资远高于其他部门
数据可视化的目的是让数据说话,让人在几秒内理解背后的规律和故事。
安装与导入
# 安装(通常已预装)
# pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np
# 在 Jupyter Notebook 中显示图表
# %matplotlib inline
导入约定
import matplotlib.pyplot as plt 是固定写法,整个数据科学社区都这么用。
第一张图:5 行代码
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
plt.plot(x, y) # 绘制折线图
plt.title("我的第一张图") # 标题
plt.show() # 显示图表
就这么简单!你会看到一条从左下到右上的直线。
核心概念:Figure 和 Axes
Matplotlib 的图表由两个核心对象组成:
- Figure:整张画布,可以包含多个子图
- Axes:一个具体的图表区域(注意不是"轴",而是"子图")
两种绑图风格
# 风格 1:plt 快速绘图(简单场景用这个)
plt.plot([1, 2, 3], [4, 5, 6])
plt.title("快速绘图")
plt.show()
# 风格 2:面向对象(推荐,更灵活)
fig, ax = plt.subplots() # 创建画布和子图
ax.plot([1, 2, 3], [4, 5, 6]) # 在子图上绑制
ax.set_title("面向对象绘图") # 设置标题
plt.show()
推荐使用面向对象风格
虽然 plt.plot() 更简单,但面向对象风格(fig, ax = plt.subplots())在需要多个子图或精细控制时更方便。建议从一开始就养成这个习惯。
5 种基本图表
1. 折线图(Line Plot)
适合场景: 展示数据随时间或连续变量的变化趋势
import matplotlib.pyplot as plt
import numpy as np
# 模拟 12 个月的销售数据
months = np.arange(1, 13)
sales_2023 = [120, 135, 150, 180, 200, 210, 195, 188, 220, 250, 280, 310]
sales_2024 = [140, 155, 170, 195, 230, 245, 225, 210, 260, 290, 320, 350]
fig, ax = plt.subplots(figsize=(10, 6)) # 设置画布大小
ax.plot(months, sales_2023, marker="o", label="2023年", color="#2196F3", linewidth=2)
ax.plot(months, sales_2024, marker="s", label="2024年", color="#FF5722", linewidth=2)
ax.set_title("月度销售额趋势", fontsize=16, fontweight="bold")
ax.set_xlabel("月份", fontsize=12)
ax.set_ylabel("销售额(万元)", fontsize=12)
ax.set_xticks(months)
ax.set_xticklabels([f"{m}月" for m in months])
ax.legend(fontsize=12) # 显示图例
ax.grid(True, alpha=0.3) # 显示网格线
plt.tight_layout() # 自动调整边距
plt.show()
关键参数:
| 参数 | 作用 | 示例 |
|---|---|---|
marker | 数据点标记 | "o" 圆点, "s" 方块, "^" 三角 |
linestyle | 线型 | "-" 实线, "--" 虚线, ":" 点线 |
linewidth | 线宽 | 2 |
color | 颜色 | "red", "#FF5722", "C0" |
label | 图例标签 | "2023年" |
alpha | 透明度 | 0.7(0 全透明, 1 不透明) |
2. 柱状图(Bar Chart)
适合场景: 比较不同类别的数据大小
# 各部门薪资对比
departments = ["技术部", "市场部", "管理部", "财务部", "人事部"]
avg_salary = [18500, 16200, 28000, 15800, 14500]
fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(departments, avg_salary, color=["#4CAF50", "#2196F3", "#FF9800", "#9C27B0", "#607D8B"])
# 在柱子上方显示数值
for bar, val in zip(bars, avg_salary):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 300,
f"¥{val:,}", ha="center", fontsize=10)
ax.set_title("各部门平均薪资", fontsize=14)
ax.set_ylabel("薪资(元)")
ax.set_ylim(0, max(avg_salary) * 1.15) # Y 轴留出数值标签的空间
plt.tight_layout()
plt.show()
水平柱状图(数据标签较长时更好看):
fig, ax = plt.subplots(figsize=(8, 5))
ax.barh(departments, avg_salary, color="#4CAF50")
ax.set_xlabel("薪资(元)")
ax.set_title("各部门平均薪资")
plt.tight_layout()
plt.show()
分组柱状图:
# 两年对比
x = np.arange(len(departments))
width = 0.35
fig, ax = plt.subplots(figsize=(10, 5))
ax.bar(x - width/2, [17000, 15000, 26000, 14500, 13000], width, label="2023", color="#64B5F6")
ax.bar(x + width/2, avg_salary, width, label="2024", color="#1565C0")
ax.set_xticks(x)
ax.set_xticklabels(departments)
ax.legend()
ax.set_title("各部门薪资对比(2023 vs 2024)")
plt.tight_layout()
plt.show()
3. 散点图(Scatter Plot)
适合场景: 观察两个变量之间的关系
np.random.seed(42)
# 模拟身高和体重数据
height = np.random.normal(170, 8, 100)
weight = height * 0.65 - 40 + np.random.normal(0, 5, 100)
fig, ax = plt.subplots(figsize=(8, 6))
scatter = ax.scatter(height, weight, c=weight, cmap="RdYlGn_r",
s=50, alpha=0.7, edgecolors="white", linewidth=0.5)
ax.set_title("身高与体重的关系", fontsize=14)
ax.set_xlabel("身高(cm)")
ax.set_ylabel("体重(kg)")
plt.colorbar(scatter, label="体重") # 颜色条
plt.tight_layout()
plt.show()
关键参数:
| 参数 | 作用 | 示例 |
|---|---|---|
s | 点的大小 | 50, 或传入数组让大小不同 |
c | 点的颜色 | "red", 或传入数组做颜色映射 |
cmap | 颜色映射 | "viridis", "RdYlGn", "Blues" |
alpha | 透明度 | 0.7 |
4. 直方图(Histogram)
适合场景: 查看数据的分布情况
np.random.seed(42)
scores = np.random.normal(75, 12, 500) # 500 个学生的成绩
fig, ax = plt.subplots(figsize=(8, 5))
# 绘制直方图
n, bins, patches = ax.hist(scores, bins=20, color="#42A5F5", edgecolor="white",
alpha=0.8)
# 添加均值线
mean_val = scores.mean()
ax.axvline(mean_val, color="red", linestyle="--", linewidth=2, label=f"均值: {mean_val:.1f}")
ax.set_title("学生成绩分布", fontsize=14)
ax.set_xlabel("分数")
ax.set_ylabel("人数")
ax.legend()
plt.tight_layout()
plt.show()
5. 饼图(Pie Chart)
适合场景: 展示各部分占整体的比例(类别不超过 5-6 个)
labels = ["Python", "JavaScript", "Java", "C++", "其他"]
sizes = [35, 25, 20, 10, 10]
colors = ["#4CAF50", "#FFC107", "#2196F3", "#FF5722", "#9E9E9E"]
explode = (0.05, 0, 0, 0, 0) # 突出 Python
fig, ax = plt.subplots(figsize=(7, 7))
ax.pie(sizes, explode=explode, labels=labels, colors=colors,
autopct="%1.1f%%", startangle=90, shadow=False,
textprops={"fontsize": 12})
ax.set_title("AI 领域编程语言使用占比", fontsize=14)
plt.tight_layout()
plt.show()
饼图慎用
饼图在类别多(大于 6 个)或比例接近时很难看清差异。大多数情况下,柱状图比饼图更好。只有在强调"部分占总体"的关系时才用饼图。