Python 从入门到实战(十一):数据可视化(用图表让数据 “说话”)

文章目录

    • [一、为什么需要数据可视化?先看 "数字 vs 图表" 的差距](#一、为什么需要数据可视化?先看 “数字 vs 图表” 的差距)
    • [二、可视化基础:Matplotlib 入门(基础图表绘制)](#二、可视化基础:Matplotlib 入门(基础图表绘制))
      • [1. 安装与基础配置](#1. 安装与基础配置)
        • [▶ 安装 Matplotlib](#▶ 安装 Matplotlib)
        • [▶ 基础配置(解决中文字体乱码)](#▶ 基础配置(解决中文字体乱码))
      • [2. 核心概念:Matplotlib 的 "图层" 逻辑](#2. 核心概念:Matplotlib 的 “图层” 逻辑)
      • [3. 实战 1:柱状图(对比数据大小)](#3. 实战 1:柱状图(对比数据大小))
      • [4. 实战 2:饼图(展示数据占比)](#4. 实战 2:饼图(展示数据占比))
      • [5. 实战 3:折线图(展示数据趋势)](#5. 实战 3:折线图(展示数据趋势))
    • [三、可视化进阶:Seaborn 美化与复杂图表](#三、可视化进阶:Seaborn 美化与复杂图表)
      • [1. 安装与基础配置](#1. 安装与基础配置)
        • [▶ 安装 Seaborn](#▶ 安装 Seaborn)
        • [▶ 基础配置(启用 Seaborn 样式)](#▶ 基础配置(启用 Seaborn 样式))
      • [2. 实战 1:箱线图(展示数据分布与异常值)](#2. 实战 1:箱线图(展示数据分布与异常值))
        • [示例:用 Seaborn 绘制 "各科成绩箱线图"](#示例:用 Seaborn 绘制 “各科成绩箱线图”)
        • 箱线图解读
        • 运行结果
      • [3. 实战 2:热力图(展示变量间的相关性)](#3. 实战 2:热力图(展示变量间的相关性))
        • [示例:用 Seaborn 绘制 "学生 - 课程成绩热力图"](#示例:用 Seaborn 绘制 “学生 - 课程成绩热力图”)
        • 运行结果
        • 热力图适用场景
    • 四、综合实操:学生成绩可视化报告(多图表组合)
    • [五、新手必踩的 5 个坑:避坑指南](#五、新手必踩的 5 个坑:避坑指南)
      • [坑 1:中文字体乱码(最常见)](#坑 1:中文字体乱码(最常见))
      • [坑 2:子图布局重叠(标签被截断)](#坑 2:子图布局重叠(标签被截断))
      • [坑 3:Seaborn 和 Matplotlib 样式冲突](#坑 3:Seaborn 和 Matplotlib 样式冲突)
      • [坑 4:饼图标签拥挤(类别过多)](#坑 4:饼图标签拥挤(类别过多))
      • [坑 5:保存图表时标签被截断](#坑 5:保存图表时标签被截断)
    • 六、小结与下一篇预告

欢迎回到「Python 从入门到实战」系列专栏。上一篇咱们用 Pandas 搞定了学生成绩的筛选、清洗和统计 ------ 比如算出 "数学平均分 86 分""小红是优秀学生",但这些数字总感觉不够直观:各科成绩差距有多大?成绩等级分布是否均衡?不同学生的总分对比如何?只看数字很难快速 get 到这些信息。

今天咱们要学 Python 数据可视化的 "双王牌"------MatplotlibSeaborn。它们就像数据的 "化妆师",能把枯燥的数字变成直观的图表(柱状图、折线图、饼图等),让数据的趋势、分布、对比关系一目了然。咱们会从基础的 "Matplotlib 绘图" 入手,再用 Seaborn 美化图表,最后结合上一篇的学生成绩数据,实战生成 "成绩分析可视化报告",让你的数据分析结果既有深度又有颜值。

一、为什么需要数据可视化?先看 "数字 vs 图表" 的差距

上一篇我们用 Pandas 统计了学生成绩的核心信息,比如:

  • 数学平均分 86.0,英语平均分 87.3;
  • 成绩等级分布:A 级 2 人,B 级 3 人,C 级 1 人;
  • 学生总分:小红 183 分,小明 177 分,小刚 160 分。

这些数字很准确,但不够直观 ------ 比如 "各科平均分差距",你需要手动计算差值(87.3-86.0=1.3)才能知道差距小;而用柱状图展示,一眼就能看出两科分数的高度差异:

数字统计 柱状图可视化
数学平均分 86.0,英语平均分 87.3 (示意:英语柱略高于数学柱)

再比如 "成绩等级分布",数字 "A 级 2 人、B 级 3 人、C 级 1 人" 需要在脑子里换算比例;而用饼图展示,各等级的占比一眼就能看清:

数字统计 饼图可视化
A 级 2 人、B 级 3 人、C 级 1 人 (示意:B 级占比最大,约 50%)

这就是数据可视化的核心价值:将抽象数字转化为直观图形,降低理解成本,快速传递数据洞察

二、可视化基础:Matplotlib 入门(基础图表绘制)

Matplotlib 是 Python 最核心的可视化库,几乎所有其他可视化库(包括 Seaborn)都基于它开发。它支持绘制折线图、柱状图、饼图等多种图表,灵活性极高。咱们先从 "安装" 和 "基础配置" 入手,再实战绘制常用图表。

1. 安装与基础配置

▶ 安装 Matplotlib

打开终端 / 命令提示符,输入以下命令安装:

bash

bash 复制代码
pip install matplotlib
▶ 基础配置(解决中文字体乱码)

Matplotlib 默认不支持中文字体,直接绘图会出现 "方框乱码",需要提前配置。在代码开头添加以下配置(复制即用):

python

python 复制代码
import matplotlib.pyplot as plt
import pandas as pd

# 解决中文字体乱码(Windows用SimHei,macOS用PingFang SC)
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']  # 中文支持
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

2. 核心概念:Matplotlib 的 "图层" 逻辑

Matplotlib 绘图像 "叠报纸",有三个核心图层,理解它们才能灵活调整图表:

  1. Figure(画布):最外层的 "大画板",所有图表都在画布上绘制;
  2. Axes(子图):画布上的 "小画板",一个画布可以有多个子图(比如一行两列的子图);
  3. 元素(标签、标题、图例):绘制在 Axes 上的细节,比如轴标签、图表标题、图例等。

简单来说:先创建 "画布(Figure)",再在画布上划分 "子图(Axes)",最后在子图上添加 "元素"。

3. 实战 1:柱状图(对比数据大小)

柱状图适合 "对比不同类别数据的大小",比如各科平均分、各学生总分。

示例:用柱状图展示 "各科平均分"

用上一篇的学生成绩数据,先通过 Pandas 计算各科平均分,再用 Matplotlib 绘制柱状图:

python

python 复制代码
import matplotlib.pyplot as plt
import pandas as pd

# 1. 配置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

# 2. 读取数据(上一篇的学生成绩数据)
df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

# 3. 用Pandas计算各科平均分
course_avg = df.groupby("course_name")["course_score"].mean().round(1)
print("各科平均分:")
print(course_avg)

# 4. 绘制柱状图
# 创建画布(figsize:宽8英寸,高5英寸;dpi:分辨率)
fig, ax = plt.subplots(figsize=(8, 5), dpi=100)

# 绘制柱状图(x=课程名,y=平均分,颜色=蓝色,边框=黑色)
bars = ax.bar(
    x=course_avg.index,  # x轴:课程名
    height=course_avg.values,  # y轴:平均分
    color='skyblue',  # 柱体颜色
    edgecolor='black'  # 柱体边框颜色
)

# 5. 添加图表元素(标题、轴标签、数值标签)
ax.set_title("学生各科平均分对比", fontsize=14, pad=20)  # 标题(字号14,距离轴20像素)
ax.set_xlabel("课程名称", fontsize=12)  # x轴标签
ax.set_ylabel("平均分(分)", fontsize=12)  # y轴标签

# 在每个柱子顶部添加数值标签
for bar in bars:
    height = bar.get_height()  # 获取柱子高度(即平均分)
    ax.text(
        bar.get_x() + bar.get_width()/2,  # x坐标:柱子中心
        height + 0.5,  # y坐标:柱子顶部+0.5(避免和柱子重叠)
        str(height),  # 显示的数值
        ha='center', va='bottom', fontsize=11  # 水平居中、垂直靠下
    )

# 6. 调整y轴范围(让图表更美观)
ax.set_ylim(80, 90)  # y轴从80到90,突出差距

# 7. 保存图表(bbox_inches='tight':避免标签被截断)
plt.savefig("course_avg_bar.png", bbox_inches='tight')
# 显示图表(Jupyter Notebook中需加plt.show())
plt.show()
运行结果
  • 控制台输出

    plaintext

    plaintext 复制代码
    各科平均分:
    course_name
    数学    86.0
    英语    87.3
    Name: course_score, dtype: float64
  • 生成的图表course_avg_bar.png(蓝色柱状图,数学柱高 86.0,英语柱高 87.3,顶部有数值标签,标题和轴标签清晰)。

柱状图适用场景
  • 对比不同类别的数据(如各科成绩、各部门销售额);
  • 展示单一指标在不同维度的大小差异。

4. 实战 2:饼图(展示数据占比)

饼图适合 "展示各部分占总体的比例",比如成绩等级分布、各年龄段学生占比。

示例:用饼图展示 "成绩等级分布"

python

python 复制代码
import matplotlib.pyplot as plt
import pandas as pd

# 1. 配置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

# 2. 读取数据并计算等级分布
df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})
# 添加成绩等级列
df["grade"] = df["course_score"].apply(lambda x: "A级(90+)" if x >=90 else ("B级(80-89)" if x>=80 else "C级(<80)"))
# 统计各等级数量
grade_count = df["grade"].value_counts()
print("成绩等级分布:")
print(grade_count)

# 3. 绘制饼图
fig, ax = plt.subplots(figsize=(6, 6), dpi=100)

# 定义颜色(避免默认颜色单调)
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1']

# 绘制饼图(autopct:显示百分比;startangle:起始角度;explode:突出某部分)
wedges, texts, autotexts = ax.pie(
    x=grade_count.values,  # 各部分数量
    labels=grade_count.index,  # 各部分标签
    autopct='%1.1f%%',  # 显示百分比(保留1位小数)
    startangle=90,  # 起始角度90度(让饼图更美观)
    colors=colors,  # 颜色列表
    explode=(0.05, 0, 0)  # 突出A级(偏移5%)
)

# 4. 美化饼图(调整文字样式)
ax.set_title("学生成绩等级分布", fontsize=14, pad=20)
# 调整百分比文字颜色和字号
for autotext in autotexts:
    autotext.set_color('white')  # 百分比文字白色
    autotext.set_fontsize(11)

# 5. 保存图表
plt.savefig("grade_pie.png", bbox_inches='tight')
plt.show()
运行结果
  • 控制台输出

    plaintext

    plaintext 复制代码
    成绩等级分布:
    grade
    B级(80-89)    3
    A级(90+)      2
    C级(<80)      1
    Name: count, dtype: int64
  • 生成的图表grade_pie.png(圆形饼图,B 级占 50.0%,A 级占 33.3%,C 级占 16.7%,A 级部分轻微突出,百分比文字白色醒目)。

饼图适用场景
  • 展示各部分占总体的比例(如市场份额、成绩等级占比);
  • 类别数量不宜过多(建议不超过 6 类,否则饼图会拥挤)。

5. 实战 3:折线图(展示数据趋势)

折线图适合 "展示数据随时间或顺序的变化趋势",比如学生总分排名、月度销售额变化。

示例:用折线图展示 "学生总分排名"

python

python 复制代码
import matplotlib.pyplot as plt
import pandas as pd

# 1. 配置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

# 2. 读取数据并计算学生总分
df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})
# 按姓名分组计算总分,按总分降序排序
student_total = df.groupby("name")["course_score"].sum().sort_values(ascending=False).reset_index()
print("学生总分排名:")
print(student_total)

# 3. 绘制折线图
fig, ax = plt.subplots(figsize=(8, 5), dpi=100)

# 绘制折线图(marker:添加数据点;linewidth:线宽;markersize:点大小)
ax.plot(
    student_total["name"],  # x轴:学生姓名
    student_total["course_score"],  # y轴:总分
    marker='o',  # 数据点为圆形
    linewidth=2,  # 线宽2像素
    markersize=8,  # 数据点大小8
    color='#FF6B6B'  # 线和点的颜色
)

# 4. 添加图表元素
ax.set_title("学生总分排名趋势", fontsize=14, pad=20)
ax.set_xlabel("学生姓名", fontsize=12)
ax.set_ylabel("总分(分)", fontsize=12)
ax.grid(True, alpha=0.3)  # 添加网格(透明度0.3,不影响数据)

# 在每个数据点上添加数值标签
for i, row in student_total.iterrows():
    ax.text(
        i,  # x坐标:行索引(0,1,2)
        row["course_score"] + 2,  # y坐标:总分+2(避免重叠)
        str(row["course_score"]),  # 显示的数值
        ha='center', va='bottom', fontsize=11
    )

# 5. 调整y轴范围
ax.set_ylim(150, 190)

# 6. 保存图表
plt.savefig("student_total_line.png", bbox_inches='tight')
plt.show()
运行结果
  • 控制台输出

    plaintext

    plaintext 复制代码
    学生总分排名:
      name  course_score
    0   小红           183
    1   小明           177
    2   小刚           160
  • 生成的图表student_total_line.png(红色折线,从左到右依次是小红 183、小明 177、小刚 160,数据点为圆形,顶部有数值标签,背景有浅灰色网格)。

折线图适用场景
  • 展示数据随顺序或时间的变化趋势(如排名、时间序列);
  • 对比多个数据系列的趋势(如多个学生的多科成绩变化)。

三、可视化进阶:Seaborn 美化与复杂图表

Matplotlib 功能强大,但默认样式比较朴素;Seaborn 是基于 Matplotlib 的高级库,自带美观的样式和复杂图表(如箱线图、热力图),一行代码就能让图表颜值翻倍。

1. 安装与基础配置

▶ 安装 Seaborn

bash

bash 复制代码
pip install seaborn
▶ 基础配置(启用 Seaborn 样式)

Seaborn 可以直接调用 Matplotlib 的 API,也可以用自己的样式:

python

python 复制代码
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 1. 启用Seaborn默认样式(美观且无需手动调颜色)
sns.set_style("whitegrid")  # 白色网格背景(适合大多数图表)
# 2. 解决中文字体(Seaborn依赖Matplotlib的字体配置)
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

2. 实战 1:箱线图(展示数据分布与异常值)

箱线图适合 "展示数据的分布特征(中位数、四分位数、异常值)",比如各科成绩的分布范围、是否有异常高分 / 低分。

示例:用 Seaborn 绘制 "各科成绩箱线图"

python

python 复制代码
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 1. 配置样式和中文字体
sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

# 2. 读取数据
df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

# 3. 绘制箱线图(Seaborn一行代码)
fig, ax = plt.subplots(figsize=(8, 5), dpi=100)
sns.boxplot(
    x="course_name",  # x轴:课程名
    y="course_score",  # y轴:成绩
    data=df,  # 数据源
    palette="Set2",  # 颜色主题
    ax=ax  # 指定子图(和Matplotlib兼容)
)

# 4. 添加图表元素
ax.set_title("各科成绩分布箱线图", fontsize=14, pad=20)
ax.set_xlabel("课程名称", fontsize=12)
ax.set_ylabel("成绩(分)", fontsize=12)
# 调整y轴范围(0-100,符合成绩逻辑)
ax.set_ylim(0, 100)

# 5. 保存图表
plt.savefig("course_score_box.png", bbox_inches='tight')
plt.show()
箱线图解读

箱线图的每个 "箱子" 代表数据的核心分布:

  • 箱子中间的线:中位数(50% 分位数);
  • 箱子上下沿:25% 分位数和 75% 分位数(中间 50% 的数据在箱子内);
  • 箱子外的线(须):数据的合理范围(通常是 1.5 倍四分位距);
  • 须外的点:异常值(如 0 分或 100 分以外的极端值)。
运行结果

生成的course_score_box.png中,数学和英语的箱子清晰展示了各自的成绩分布 ------ 比如数学成绩的中位数略低于英语,说明英语整体成绩稍好,且两科都没有异常值。

3. 实战 2:热力图(展示变量间的相关性)

热力图适合 "展示两个分类变量的交叉统计结果",比如 "学生 - 课程 - 成绩" 的交叉表,用颜色深浅表示成绩高低。

示例:用 Seaborn 绘制 "学生 - 课程成绩热力图"

python

python 复制代码
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 1. 配置样式和中文字体
sns.set_style("white")  # 白色背景(热力图适合无网格)
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

# 2. 读取数据并创建交叉表(学生-课程-成绩)
df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})
# 创建交叉表:行=学生,列=课程,值=成绩
score_cross = df.pivot_table(
    index="name",  # 行:学生姓名
    columns="course_name",  # 列:课程名
    values="course_score"  # 值:成绩
)
print("学生-课程成绩交叉表:")
print(score_cross)

# 3. 绘制热力图
fig, ax = plt.subplots(figsize=(6, 4), dpi=100)
sns.heatmap(
    data=score_cross,  # 数据源(交叉表)
    annot=True,  # 在热力图上显示数值
    fmt="d",  # 数值格式:整数
    cmap="YlOrRd",  # 颜色映射(黄色到红色,红色表示高分)
    cbar=True,  # 显示颜色条(右侧,解释颜色含义)
    ax=ax
)

# 4. 添加图表元素
ax.set_title("学生-课程成绩热力图", fontsize=14, pad=20)
ax.set_xlabel("课程名称", fontsize=12)
ax.set_ylabel("学生姓名", fontsize=12)

# 5. 保存图表
plt.savefig("student_course_heatmap.png", bbox_inches='tight')
plt.show()
运行结果
  • 控制台输出

    plaintext

    plaintext 复制代码
    学生-课程成绩交叉表:
    course_name  数学  英语
    name               
    小明          85  92
    小红          95  88
    小刚          78  82
  • 生成的图表student_course_heatmap.png(热力图中,小红的数学成绩 95(深红色)、小明的英语成绩 92(深红色),小刚的数学成绩 78(浅黄色),颜色越深表示成绩越高,右侧颜色条标注了成绩范围)。

热力图适用场景
  • 展示两个分类变量的交叉统计(如学生 - 课程 - 成绩、产品 - 地区 - 销量);
  • 快速识别 "高值区域" 或 "低值区域"(如哪些学生在哪些课程上表现好)。

四、综合实操:学生成绩可视化报告(多图表组合)

咱们结合前面的所有图表类型,用 Matplotlib 和 Seaborn 制作一个 "学生成绩可视化报告"------ 在一个画布上绘制 4 个子图(柱状图、饼图、箱线图、热力图),形成完整的分析报告。

完整代码

python

python 复制代码
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

def student_score_visual_report(input_file="students_data.csv", output_file="score_report.png"):
    print("===== 学生成绩可视化报告生成中 =====")
    
    # 1. 全局配置(样式、中文字体、分辨率)
    sns.set_style("whitegrid")
    plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
    plt.rcParams['axes.unicode_minus'] = False
    plt.rcParams['figure.dpi'] = 100  # 全局分辨率

    # 2. 读取并预处理数据
    df = pd.read_csv(input_file, encoding="utf-8", dtype={"course_score": int})
    # 添加成绩等级列
    df["grade"] = df["course_score"].apply(lambda x: "A级(90+)" if x >=90 else ("B级(80-89)" if x>=80 else "C级(<80)"))
    # 计算辅助数据
    course_avg = df.groupby("course_name")["course_score"].mean().round(1)  # 各科平均分
    grade_count = df["grade"].value_counts()  # 成绩等级分布
    student_total = df.groupby("name")["course_score"].sum().sort_values(ascending=False).reset_index()  # 学生总分
    score_cross = df.pivot_table(index="name", columns="course_name", values="course_score")  # 交叉表

    # 3. 创建画布和4个子图(2行2列)
    fig, axes = plt.subplots(2, 2, figsize=(12, 10))  # 2行2列,总宽12,高10
    fig.suptitle("学生成绩可视化分析报告", fontsize=16, y=0.98)  # 总标题(y=0.98:靠近顶部)

    # 子图1:各科平均分柱状图(第1行第1列)
    ax1 = axes[0, 0]
    bars = ax1.bar(course_avg.index, course_avg.values, color='skyblue', edgecolor='black')
    ax1.set_title("各科平均分对比", fontsize=12)
    ax1.set_xlabel("课程名称")
    ax1.set_ylabel("平均分(分)")
    ax1.set_ylim(80, 90)
    # 添加数值标签
    for bar in bars:
        height = bar.get_height()
        ax1.text(bar.get_x()+bar.get_width()/2, height+0.5, str(height), ha='center', va='bottom')

    # 子图2:成绩等级分布饼图(第1行第2列)
    ax2 = axes[0, 1]
    colors = ['#FF6B6B', '#4ECDC4', '#45B7D1']
    wedges, texts, autotexts = ax2.pie(grade_count.values, labels=grade_count.index, autopct='%1.1f%%', 
                                       startangle=90, colors=colors, explode=(0.05, 0, 0))
    ax2.set_title("成绩等级分布", fontsize=12)
    # 美化百分比文字
    for autotext in autotexts:
        autotext.set_color('white')
        autotext.set_fontsize(10)

    # 子图3:各科成绩箱线图(第2行第1列)
    ax3 = axes[1, 0]
    sns.boxplot(x="course_name", y="course_score", data=df, palette="Set2", ax=ax3)
    ax3.set_title("各科成绩分布", fontsize=12)
    ax3.set_xlabel("课程名称")
    ax3.set_ylabel("成绩(分)")
    ax3.set_ylim(0, 100)

    # 子图4:学生-课程成绩热力图(第2行第2列)
    ax4 = axes[1, 1]
    sns.heatmap(score_cross, annot=True, fmt="d", cmap="YlOrRd", cbar=True, ax=ax4)
    ax4.set_title("学生-课程成绩热力图", fontsize=12)
    ax4.set_xlabel("课程名称")
    ax4.set_ylabel("学生姓名")

    # 4. 调整子图间距(避免标签重叠)
    plt.tight_layout()  # 自动调整间距
    plt.subplots_adjust(top=0.93)  # 预留总标题空间

    # 5. 保存报告
    plt.savefig(output_file, bbox_inches='tight', dpi=150)  # 高分辨率保存(150dpi)
    plt.close()  # 关闭画布,释放内存

    print(f"✅ 可视化报告已保存到:{output_file}")
    print("===== 报告生成完成 =====")

# 运行报告生成函数
if __name__ == "__main__":
    student_score_visual_report()

关键功能说明

  1. 多子图布局 :用plt.subplots(2, 2)创建 2 行 2 列的子图,通过axes[行索引, 列索引]访问每个子图;
  2. 全局样式:统一配置 Seaborn 样式和中文字体,确保所有子图风格一致;
  3. 间距调整plt.tight_layout()自动调整子图间距,plt.subplots_adjust(top=0.93)为总标题预留空间,避免重叠;
  4. 高分辨率保存 :保存时设置dpi=150,让图表更清晰,适合打印或插入文档。

运行结果

生成的score_report.png包含 4 个子图,从不同维度展示学生成绩:

  • 左上:各科平均分对比(英语略高);
  • 右上:成绩等级分布(B 级占比最高);
  • 左下:各科成绩分布(无异常值);
  • 右下:学生 - 课程成绩热力图(小红数学最好,小明英语最好)。

五、新手必踩的 5 个坑:避坑指南

数据可视化看似简单,但新手容易在 "字体""布局""样式" 上踩坑,导致图表不美观或报错。咱们总结 5 个高频问题:

坑 1:中文字体乱码(最常见)

python

python 复制代码
# 错误示例:未配置中文字体,图表中中文显示为方框
import matplotlib.pyplot as plt
plt.plot(["小明", "小红"], [177, 183])
plt.title("学生总分")
plt.show()  # 标题"学生总分"显示为方框

解决:在代码开头添加字体配置:

python

python 复制代码
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False

坑 2:子图布局重叠(标签被截断)

python

python 复制代码
# 错误示例:多子图未调整间距,标签重叠
fig, axes = plt.subplots(2, 2, figsize=(8, 6))
# 绘制4个子图后,标签重叠
plt.savefig("overlap.png")  # 部分标签被截断

解决 :添加plt.tight_layout()自动调整间距,或plt.subplots_adjust()手动调整:

python

python 复制代码
plt.tight_layout()  # 自动调整
# 或手动调整上下左右间距
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)

坑 3:Seaborn 和 Matplotlib 样式冲突

python

python 复制代码
# 错误示例:先画Matplotlib图表,再启用Seaborn样式,样式不生效
import seaborn as sns
import matplotlib.pyplot as plt

# 先画图表,再启用样式
plt.plot([1,2,3], [4,5,6])
sns.set_style("whitegrid")  # 样式不生效
plt.show()

解决:先启用 Seaborn 样式,再绘制图表:

python

python 复制代码
sns.set_style("whitegrid")  # 先启用样式
plt.plot([1,2,3], [4,5,6])  # 再画图表
plt.show()

坑 4:饼图标签拥挤(类别过多)

python

python 复制代码
# 错误示例:饼图类别超过6个,标签拥挤
grade_count = pd.Series([1,2,3,4,5,6,7], index=[f"等级{i}" for i in range(7)])
plt.pie(grade_count.values, labels=grade_count.index)
plt.show()  # 标签重叠,无法看清

解决 :减少类别数量(合并相似类别),或用labeldistance调整标签距离:

python

python 复制代码
plt.pie(grade_count.values, labels=grade_count.index, labeldistance=1.2)  # 标签远离饼图

坑 5:保存图表时标签被截断

python

python 复制代码
# 错误示例:未加bbox_inches='tight',标题被截断
plt.plot([1,2,3], [4,5,6])
plt.title("这是一个很长的标题,用来测试保存时是否被截断")
plt.savefig("cutoff.png")  # 标题右侧被截断

解决 :保存时添加bbox_inches='tight'

python

python 复制代码
plt.savefig("cutoff.png", bbox_inches='tight')  # 自动适配所有标签

六、小结与下一篇预告

这篇你学到了什么?

  1. 可视化基础:理解数据可视化的价值,掌握 Matplotlib 的 "画布 - 子图 - 元素" 逻辑;
  2. Matplotlib 实战:绘制柱状图(对比)、饼图(占比)、折线图(趋势),添加标题、标签、数值等元素;
  3. Seaborn 进阶:用 Seaborn 美化图表,绘制箱线图(分布)、热力图(交叉统计),一行代码提升颜值;
  4. 综合报告:制作多子图的可视化报告,调整布局和分辨率,生成完整分析结果;
  5. 避坑指南:解决中文字体、子图重叠、样式冲突等常见问题。

下一篇预告

今天的可视化让数据 "说话",但前面的所有知识都是 "单机运行"------ 如果想让你的学生管理系统被多人访问(比如老师和学生都能查看成绩),就需要开发 Web 应用。下一篇咱们会学 Python 的 Web 框架Flask,结合前面的 Pandas 和可视化知识,开发一个 "在线学生成绩管理系统",支持浏览器访问、数据查询和图表展示,让你的项目从 "本地工具" 升级为 "Web 应用"。

如果这篇内容帮你掌握了数据可视化,欢迎在评论区分享你的 "可视化作品"(比如用图表分析你的消费数据),咱们一起交流进步~

相关推荐
猷咪10 分钟前
C++基础
开发语言·c++
IT·小灰灰11 分钟前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧13 分钟前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q13 分钟前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳013 分钟前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾14 分钟前
php 对接deepseek
android·开发语言·php
vx_BS8133017 分钟前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
2601_9498683617 分钟前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
gzxx2007sddx24 分钟前
windows vnpy运行过程及问题记录
python·量化·vnpy
星火开发设计31 分钟前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识