Matplotlib & Seaborn 数据可视化

标签: #Python #Matplotlib #Seaborn #数据可视化
学习周期:1.5 天 | 核心目标:掌握 Matplotlib 和 Seaborn 的基本绘图方法,能完成图表美化、子图布局及统计可视化


4.3 Matplotlib & Seaborn(可视化)

数据可视化是数据分析的关键环节,通过图形直观展示数据规律。Matplotlib 是 Python 最基础的绘图库,Seaborn 是基于 Matplotlib 的高级统计绘图库,语法更简洁,样式更美观。

  • Matplotlib:灵活性极高,可绘制几乎所有类型的图表,是后续所有可视化库的基础,缺点是默认样式较朴素,代码量稍多。
  • Seaborn:默认样式更美观,封装了大量高级统计图表(如热力图、pairplot),代码更简洁,适合快速完成统计可视化。

安装与导入

pip install matplotlib seaborn
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

# 设置中文显示(解决 Matplotlib 中文乱码)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 或 ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题

# Seaborn 设置样式(全局)
sns.set_style("whitegrid")   # 白色网格样式,简洁美观

4.3.1 基本绘图:折线图、散点图、柱状图、直方图、箱线图

1. 折线图(Line Plot)

适合展示数据随时间变化的趋势。

x = np.arange(1, 11)   # [1,2,...,10]
y1 = np.array([5, 7, 6, 9, 8, 12, 10, 13, 11, 15])
y2 = np.array([3, 5, 7, 6, 8, 9, 11, 12, 14, 16])

# Matplotlib 绘制
plt.plot(x, y1, label="产品A", color="blue", linewidth=2, marker="o")
plt.plot(x, y2, label="产品B", color="red", linewidth=2, marker="s", linestyle="--")
plt.title("产品销量随时间变化趋势", fontsize=14)
plt.xlabel("时间(天)", fontsize=12)
plt.ylabel("销量(件)", fontsize=12)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# Seaborn 绘制(更简洁)
sns.lineplot(x=x, y=y1, label="产品A", marker="o")
sns.lineplot(x=x, y=y2, label="产品B", marker="s", linestyle="--")
plt.title("产品销量随时间变化趋势", fontsize=14)
plt.show()

关键参数

  • color:折线颜色
  • linewidth:线宽
  • marker:数据点标记(o圆点、s方形、^三角形)
  • linestyle:线型(-实线、--虚线、-.点划线)

2. 散点图(Scatter Plot)

展示两个变量之间的关系。

# 生成数据:学习时间与成绩正相关
np.random.seed(42)
study_time = np.random.randint(1, 10, 50)
score = study_time * 8 + np.random.randn(50) * 2

# Matplotlib 绘制
plt.scatter(study_time, score, color="green", alpha=0.6, s=50, edgecolor="black")
plt.title("学习时间与成绩相关性", fontsize=14)
plt.xlabel("学习时间(小时)")
plt.ylabel("成绩(分)")
plt.show()

# Seaborn 绘制(支持按类别着色)
df = pd.DataFrame({"study_time": study_time, "score": score})
sns.scatterplot(x="study_time", y="score", data=df, color="green", alpha=0.7)
plt.show()

3. 柱状图(Bar Plot)

比较不同类别的数值大小。

categories = ['一班', '二班', '三班', '四班']
values = [85.2, 79.5, 88.1, 82.7]

# Matplotlib 绘制
plt.bar(categories, values, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'], edgecolor='black')
plt.title("不同班级平均分对比", fontsize=14)
plt.ylabel("平均分(分)")
for i, v in enumerate(values):
    plt.text(i, v + 0.5, str(v), ha='center')
plt.show()

# Seaborn 绘制
sns.barplot(x=categories, y=values, palette="Blues", edgecolor='black')
plt.title("不同班级平均分对比", fontsize=14)
plt.show()

4. 直方图(Histogram)

展示数据分布。

scores = np.random.normal(80, 5, 1000)  # 均值80,标准差5

# Matplotlib 绘制
plt.hist(scores, bins=15, color="skyblue", edgecolor="black", alpha=0.7)
plt.axvline(scores.mean(), color="red", linestyle="--", label=f"均值:{scores.mean():.1f}")
plt.title("学生成绩分布直方图")
plt.xlabel("成绩(分)")
plt.ylabel("学生人数")
plt.legend()
plt.show()

# Seaborn 绘制(含核密度曲线)
sns.histplot(scores, bins=15, kde=True, color="skyblue", edgecolor="black")
plt.axvline(scores.mean(), color="red", linestyle="--")
plt.show()

5. 箱线图(Box Plot)

展示数据的分布、中位数、四分位数及异常值。

# 生成三组数据
class1 = np.random.normal(80, 5, 50)
class2 = np.random.normal(75, 8, 50)
class3 = np.random.normal(85, 6, 50)

# Matplotlib 绘制
plt.boxplot([class1, class2, class3], labels=["一班", "二班", "三班"], patch_artist=True)
plt.title("不同班级成绩箱线图")
plt.ylabel("成绩(分)")
plt.show()

# Seaborn 绘制
df = pd.DataFrame({
    "成绩": np.concatenate([class1, class2, class3]),
    "班级": ["一班"]*50 + ["二班"]*50 + ["三班"]*50
})
sns.boxplot(x="班级", y="成绩", data=df, palette="lightblue")
plt.show()

4.3.2 子图布局:plt.subplots()

使用 subplots 可以在一张图中创建多个子图,方便对比。

# 创建 2x2 子图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 子图1:折线图
axes[0, 0].plot(x, y1, 'b-o')
axes[0, 0].set_title('折线图')

# 子图2:散点图
axes[0, 1].scatter(study_time, score, alpha=0.6)
axes[0, 1].set_title('散点图')

# 子图3:柱状图
axes[1, 0].bar(categories, values, color='skyblue')
axes[1, 0].set_title('柱状图')

# 子图4:直方图
axes[1, 1].hist(scores, bins=20, edgecolor='black')
axes[1, 1].set_title('直方图')

plt.tight_layout()   # 自动调整间距
plt.show()

关键技巧

  • figsize=(宽, 高):单位为英寸,根据子图数量调整。
  • 子图的标题、标签需用 axes[i,j].set_title(),而非 plt.title()
  • plt.tight_layout() 自动调整间距,避免重叠。

4.3.3 图表美化:标题、标签、图例、颜色、样式

1. 标题与标签美化

plt.plot(x, y1, label="产品A")
plt.title("产品销量趋势", fontsize=16, fontweight="bold", color="#333333", pad=20)
plt.xlabel("时间(天)", fontsize=14, fontweight="bold")
plt.ylabel("销量(件)", fontsize=14)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.show()

2. 图例美化

plt.legend(loc="upper left", fontsize=12, frameon=True, fancybox=True, shadow=True)

3. 颜色优化

  • 使用 Seaborn 内置调色板:palette="Blues""Set2""Pastel1"
  • 自定义十六进制颜色:["#FF6B6B", "#4ECDC4", "#45B7D1"]

4. 整体样式设置

sns.set_style("whitegrid")    # 白色网格
# sns.set_style("darkgrid")   # 深色网格
# sns.set_style("white")      # 无网格

5. 细节优化(去除顶部和右侧边框、添加注释)

ax = plt.gca()
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.grid(True, linestyle="--", alpha=0.5)

# 添加注释
plt.annotate("峰值", xy=(peak_x, peak_y), xytext=(peak_x+0.5, peak_y+1),
             arrowprops=dict(arrowstyle="->", color="red"))

4.3.4 Seaborn 高级统计图:热力图、pairplot、分类图

1. 热力图(Heatmap)

展示矩阵数据(如相关系数矩阵)。

# 相关系数矩阵
df = pd.DataFrame(np.random.randn(100, 4), columns=['A', 'B', 'C', 'D'])
corr = df.corr()

sns.heatmap(corr, annot=True, cmap='RdBu_r', fmt='.2f', linewidths=0.5, square=True)
plt.title("特征相关性热力图")
plt.show()

2. pairplot(成对关系图)

展示多个数值变量两两之间的关系。

# 使用内置 iris 数据集
iris = sns.load_dataset('iris')
sns.pairplot(iris, hue='species', diag_kind='hist', markers=['o', 's', 'D'])
plt.show()

3. 分类图(Categorical Plots)

  • sns.barplot:带误差棒的柱状图
  • sns.boxplot:箱线图(按类别分组)
  • sns.violinplot:小提琴图
  • sns.countplot:计数柱状图
tips = sns.load_dataset('tips')

# 条形图
sns.barplot(x='day', y='total_bill', data=tips, palette='Blues')
plt.title("每日总账单平均值")

# 箱线图
sns.boxplot(x='day', y='total_bill', data=tips, palette='Set2')

# 小提琴图
sns.violinplot(x='day', y='total_bill', data=tips, palette='muted')

练习项目:Titanic 数据集分析(不同船舱等级的存活率)

需求:分析 Titanic 数据集中不同船舱等级(Pclass)的存活率,并用柱状图展示结果。

步骤与代码

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 1. 加载数据(Seaborn 内置或本地文件)
titanic = sns.load_dataset('titanic')   # 或 pd.read_csv('train.csv')

# 2. 计算不同船舱等级的存活率
survival_rate = titanic.groupby('pclass')['survived'].mean()
print(survival_rate)
# 输出示例:
# pclass
# 1    0.629630
# 2    0.472826
# 3    0.242363

# 3. 绘制柱状图
plt.figure(figsize=(8, 6))
ax = sns.barplot(x='pclass', y='survived', data=titanic, ci=None, palette='viridis')
plt.title('不同船舱等级(Pclass)的存活率', fontsize=14)
plt.xlabel('船舱等级', fontsize=12)
plt.ylabel('存活率', fontsize=12)
plt.ylim(0, 0.7)

# 添加数值标签
for i, p in enumerate(ax.patches):
    ax.annotate(f'{p.get_height()*100:.1f}%', 
                (p.get_x() + p.get_width()/2., p.get_height()),
                ha='center', va='bottom', fontsize=11)

# 美化:去除顶部和右侧边框
sns.despine()
plt.show()

# 4. 额外分析:不同等级 + 性别的存活率
sns.barplot(x='pclass', y='survived', hue='sex', data=titanic, ci=None, palette='Set2')
plt.title('不同船舱等级与性别的存活率')
plt.show()

结论

  • 一等舱存活率最高(约 63%),二等舱约 47%,三等舱约 24%。
  • 女性存活率普遍高于男性,且一等舱女性存活率接近 97%。

📚 学习资料(Obsidian 可直接收藏)


🎯 学习建议(1.5 天计划)

  1. 第 1 天上午:掌握 Matplotlib 基础图形(折线图、散点图、柱状图、直方图、箱线图),练习子图布局和基础美化。
  2. 第 1 天下午:学习 Seaborn 高级统计图(热力图、pairplot、分类图),理解其与 Matplotlib 的配合。
  3. 第 2 天:完成 Titanic 数据分析项目,巩固可视化全流程。

✅ 核心要点总结

  1. Matplotlib:底层绘图库,灵活性高,适合精细控制图表。
  2. Seaborn:高级封装,语法简洁,内置漂亮样式和统计功能。
  3. 常用图形
    • 折线图:趋势
    • 散点图:相关性
    • 柱状图:比较
    • 直方图:分布
    • 箱线图:统计摘要
    • 热力图:矩阵数据
    • pairplot:多变量关系
  4. 美化要素:标题、标签、图例、颜色映射、网格、样式主题、去除多余边框。
  5. 子图布局plt.subplots() 创建多子图,tight_layout() 自动调整间距。
  6. 实战流程:数据加载 → 数据处理 → 计算指标 → 绘制图表 → 美化 → 结论分析。

练习题(自测)

  1. 绘制一个包含两条曲线的折线图,添加图例、网格和标题。
  2. 生成两组随机数据,绘制散点图并添加回归线(可使用 Seaborn 的 regplot)。
  3. 创建一个 2×2 的子图布局,分别绘制柱状图、箱线图、直方图和热力图。
  4. 使用 Seaborn 的 pairplot 分析 iris 数据集,按 species 着色。
  5. 完成 Titanic 项目后,尝试分析“年龄分布与存活率”的关系,用直方图或箱线图展示。

建议使用 Jupyter Notebook 逐行运行示例,观察图表效果并修改参数。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐