动态规划算法实践:从斐波那契到数字推理

Python数据可视化实战:matplotlib进阶技巧学习笔记

前言

数据可视化是数据分析中非常重要的环节,良好的可视化能够让数据更加直观、易懂。本文基于三个实际的数据可视化案例,总结了matplotlib的进阶使用技巧,包括多子图布局、图表美化、数据标注等核心技能。每个案例都包含完整的代码实现,方便读者学习和实践。

案例一:时间序列数据的多子图展示

功能概述

这段代码展示了如何使用matplotlib创建多个子图来展示不同指标的时间序列数据,包括规模以上工业、钢材、十种有色金属的同比增长速度。通过垂直排列的三个子图,实现了数据的清晰对比和展示。

完整代码实现

python 复制代码
import matplotlib.pyplot as plt
import numpy as np

# 数据准备
x_month = np.array(['2022年\n11月', '12月', '2023年\n1-2月', 
                    '3月', '4月', '5月', '6月', '7月', '8月', 
                    '9月', '10月', '11月'])
industry_rate = np.array([2.2, 1.3, 2.4, 3.9, 5.6, 3.5, 4.4, 3.7, 
                          4.5, 4.5, 4.6, 6.6])
steels_rate = np.array([7.1, -2.6, 3.6, 8.1, 5.0, -1.3, 5.4, 14.5, 
                        11.4, 5.5, 3.0, 4.2])
metal_rate = np.array([8.8, 7.3, 9.8, 6.9, 6.1, 5.1, 6.1, 4.2, 
                       6.1, 7.3, 8.2, 7.1])

# 创建画布(3行1列,共享x轴)
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 6), sharex=True)
plt.subplots_adjust(hspace=0.6)  # 调整子图间距


# 1. 规模以上工业同比增速(线居中 + 刻度拉高)
ax1.plot(x_month, industry_rate, marker='o', color='r', linewidth=2)
ax1.set_title('规模以上工业同比增长速度', fontsize=12, pad=10)
ax1.set_ylabel('增长速度(%)', fontsize=10)

# 数据范围:min=1.3,max=6.6 → 设Y轴范围为0~8(上限拉高到8,下方留0作为余量)
# 此时折线中间值(~3.9)位于0~8的中间(4)附近,实现居中
ax1.set_ylim(0, 8)  
# 标注数据
for i, rate in enumerate(industry_rate):
    ax1.text(i, rate + 0.2, f'{rate}', ha='center', va='bottom', fontsize=8)


# 2. 钢材同比增速(线居中 + 刻度拉高)
ax2.plot(x_month, steels_rate, marker='o', color='g', linewidth=2)
ax2.set_title('钢材同比增长速度', fontsize=12, pad=10)
ax2.set_ylabel('增长速度(%)', fontsize=10)

# 数据范围:min=-2.6,max=14.5 → 设Y轴范围为-5~20(上限拉高到20,下方留-5作为余量)
# 此时折线中间值(~5.9)位于-5~20的中间(7.5)附近,实现居中
ax2.set_ylim(-5, 20)  
# 标注数据(负数特殊处理)
for i, rate in enumerate(steels_rate):
    offset = 0.5 if rate >= 0 else -1.2
    ax2.text(i, rate + offset, f'{rate}', ha='center', va='bottom', fontsize=8)


# 3. 十种有色金属同比增速(线居中 + 刻度拉高)
ax3.plot(x_month, metal_rate, marker='o', color='b', linewidth=2)
ax3.set_title('十种有色金属同比增长速度', fontsize=12, pad=10)
ax3.set_xlabel('月份', fontsize=10)
ax3.set_ylabel('增长速度(%)', fontsize=10)
ax3.tick_params(axis='x', rotation=45, labelsize=9)

# 数据范围:min=4.2,max=9.8 → 设Y轴范围为0~12(上限拉高到12,下方留0作为余量)
# 此时折线中间值(~7)位于0~12的中间(6)附近,实现居中
ax3.set_ylim(0, 12)  
# 标注数据
for i, rate in enumerate(metal_rate):
    ax3.text(i, rate + 0.3, f'{rate}', ha='center', va='bottom', fontsize=8)


plt.show()

核心技巧解析

1. 多子图布局设计
python 复制代码
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 6), sharex=True)
plt.subplots_adjust(hspace=0.6)

关键点:

  • 使用sharex=True让子图共享x轴,避免重复显示
  • 通过hspace调整子图间距,确保美观
  • 合理设置figsize,保持图形比例协调
2. 折线图样式优化
python 复制代码
ax1.plot(x_month, industry_rate, marker='o', color='r', linewidth=2)

样式参数说明:

  • marker='o':添加圆形标记点
  • color='r':设置线条颜色为红色
  • linewidth=2:增加线条宽度,提高可读性
3. 坐标轴范围控制
python 复制代码
# 根据数据范围动态设置y轴范围
ax1.set_ylim(0, 8)  # 数据范围1.3-6.6,设置0-8使线条居中
ax2.set_ylim(-5, 20)  # 包含负值的数据需要特殊处理
4. 数据标注技巧
python 复制代码
for i, rate in enumerate(industry_rate):
    ax1.text(i, rate + 0.2, f'{rate}', ha='center', va='bottom', fontsize=8)

标注优化:

  • 为每个数据点添加数值标签
  • 使用ha='center'va='bottom'控制对齐方式
  • 适当调整偏移量,避免标签重叠

案例一效果特点

  • 三个子图垂直排列,共享x轴,视觉统一
  • 每个指标使用不同颜色区分(红色、绿色、蓝色)
  • 数据标注清晰,便于读取具体数值
  • 坐标轴范围设置合理,使线条居中显示

案例二:横向条形图的对比展示

功能概述

这段代码使用横向条形图对比展示了不同国家养猫和养狗人群的比例,通过双栏布局实现直观对比。横向条形图特别适合类别名称较长的情况,能够更好地展示国家名称。

完整代码实现

python 复制代码
import matplotlib.pyplot as plt
import numpy as np

# 1. 准备数据
y = np.arange(12)  # 国家对应的索引
x1 = np.array([19, 33, 28, 29, 14, 24, 57, 6, 26, 15, 27, 39])  # 养猫人群比例
x2 = np.array([25, 33, 58, 39, 15, 64, 29, 23, 22, 11, 27, 50])  # 养狗人群比例
labels = np.array(['中国', '加拿大', '巴西', '澳大利亚', '日本', '墨西哥',
                   '俄罗斯', '韩国', '瑞士', '土耳其', '英国', '美国'])  # 国家标签

# 2. 创建画布(1行2列,共享y轴,保证国家标签对齐)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 6), sharey=True)  # 适当加宽画布避免标签拥挤

# 3. 绘制"养猫人群比例"条形图
ax1.barh(y, x1, color='orange')
ax1.set_title('部分国家养猫人群的比例')
ax1.set_xlabel('人群比例/%')
ax1.set_yticks(y, labels)  # 设置y轴刻度与国家标签

# 为养猫条形图添加数值标签
for i, value in enumerate(x1):
    ax1.text(value + 1, i, f'{value}%', va='center', fontsize=8)  # 标签在条形右侧,居中对齐

# 4. 绘制"养狗人群比例"条形图
ax2.barh(y, x2, color='teal')
ax2.set_title('部分国家养狗人群的比例')
ax2.set_xlabel('人群比例/%')
ax2.set_yticks(y, labels)  # 与左图共享y轴,同步设置标签

# 为养狗条形图添加数值标签
for i, value in enumerate(x2):
    ax2.text(value + 1, i, f'{value}%', va='center', fontsize=8)  # 标签在条形右侧,居中对齐

# 5. 调整x轴范围,避免标签超出画布
ax1.set_xlim(0, max(x1) + 10)
ax2.set_xlim(0, max(x2) + 10)

# 6. 调整布局(让图形更紧凑美观)
plt.tight_layout()

# 7. 显示图形
plt.show()

核心技巧解析

1. 双栏布局设计
python 复制代码
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 6), sharey=True)

布局优势:

  • 左右双栏布局,便于直接对比
  • sharey=True确保y轴对齐,国家标签一致
  • 适当加宽figsize避免标签拥挤
2. 横向条形图绘制
python 复制代码
ax1.barh(y, x1, color='orange')
ax2.barh(y, x2, color='teal')

横向条形图适用场景:

  • 类别名称较长时(如国家名称)
  • 需要突出数值大小对比
  • 类别数量较多时
3. y轴标签设置
python 复制代码
ax1.set_yticks(y, labels)
ax2.set_yticks(y, labels)

标签优化:

  • 两个子图使用相同的y轴标签
  • 保持国家顺序一致,便于对比
  • 字体大小适中,确保可读性
4. 数值标签添加
python 复制代码
for i, value in enumerate(x1):
    ax1.text(value + 1, i, f'{value}%', va='center', fontsize=8)

标签位置优化:

  • 标签位于条形图右侧
  • 使用va='center'使标签垂直居中
  • 添加适当偏移量避免重叠

案例二效果特点

  • 左右对比清晰,一目了然
  • 颜色区分明显(橙色代表养猫,青色代表养狗)
  • 数值标签位置恰当,不影响图形美观
  • 整体布局紧凑但不拥挤

案例三:组合图表的高级布局

功能概述

这段代码展示了如何创建复杂的组合图表,包括柱状图和条形图的混合布局,用于对比抖音和快手的用户分布数据。通过gridspec实现了灵活的布局设计,展示了城市分布和年龄分布两个维度的数据。

完整代码实现

python 复制代码
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec

# 准备年龄分布数据
y_age = np.arange(5)
ages = np.array(['18岁以下', '18~24岁', '25~34岁', '35~44岁', '45岁以上'])
tiktok_age = np.array([5.8, 13.2, 23.4, 23.4, 24.8])
quicker_age = np.array([8.3, 11.0, 21.9, 25.4, 26.2])

# 准备城市分布数据
x_city = np.arange(6)
citys = np.array(['五线城市', '四线城市', '三线城市', '二线城市', '新一线城市', '一线城市'])
tiktok_city = np.array([12.1, 17.1, 16.7, 16.3, 16.5, 5.9])
quicker_city = np.array([14.4, 18.9, 17.5, 15.1, 13.9, 4.5])

# 调整画布尺寸(横向略宽,给右侧标签留空间)
fig = plt.figure(figsize=(8.5, 7))  # 宽度从8→8.5,增加右侧空间
gs = gridspec.GridSpec(2, 2, height_ratios=[1.2, 2], width_ratios=[1, 1])

# 创建子图
ax1 = fig.add_subplot(gs[0, :])  # 城市分布
ax2 = fig.add_subplot(gs[1, 0])  # 抖音年龄分布
ax3 = fig.add_subplot(gs[1, 1])  # 快手年龄分布

# -------------------------- 城市分布柱形图(ax1) --------------------------
bar_width = 0.35
tiktok_bars = ax1.bar(x_city - bar_width/2, tiktok_city, width=bar_width, label='抖音', color='teal')
quicker_bars = ax1.bar(x_city + bar_width/2, quicker_city, width=bar_width, label='快手', color='gold')

# 城市柱形标签
for bar in tiktok_bars:
    height = bar.get_height()
    ax1.text(bar.get_x() + bar.get_width()/2, height + 0.2, f'{height:.1f}%',
             ha='center', va='bottom', fontsize=8)
for bar in quicker_bars:
    height = bar.get_height()
    ax1.text(bar.get_x() + bar.get_width()/2, height + 0.2, f'{height:.1f}%',
             ha='center', va='bottom', fontsize=8)

ax1.set_xticks(x_city, citys, rotation=30, ha='right', fontsize=8)
ax1.set_title('用户城市分布', fontsize=10)
ax1.set_xlabel('城市等级', fontsize=9)
ax1.set_ylabel('比例(%)', fontsize=9)
ax1.legend(fontsize=8)
ax1.set_ylim(0, max(max(tiktok_city), max(quicker_city)) + 2)

# -------------------------- 抖音年龄分布条形图(ax2)核心优化 --------------------------
tiktok_age_bars = ax2.barh(y_age, tiktok_age, color='teal', height=0.6)  # 减小条形高度,避免拥挤

# 标签位置:紧贴条形右侧(偏移量从0.2→0.1)
for bar in tiktok_age_bars:
    width = bar.get_width()
    ax2.text(width + 0.1,  # 更靠近条形,减少偏移
             bar.get_y() + bar.get_height()/2,
             f'{width:.1f}%',
             ha='left', va='center', fontsize=8)

# 扩大x轴上限(确保标签不溢出:最大值+3,预留足够空间)
max_tiktok = max(tiktok_age)
ax2.set_xlim(0, max_tiktok + 3)  # 原+2→+3,给标签留更多空间

ax2.set_title('抖音用户年龄分布', fontsize=10)
ax2.set_xlabel('比例(%)', fontsize=9)
ax2.set_yticks(y_age, ages, fontsize=8)

# -------------------------- 快手年龄分布条形图(ax3)核心优化 --------------------------
quicker_age_bars = ax3.barh(y_age, quicker_age, color='gold', height=0.6)

# 同样减小标签偏移
for bar in quicker_age_bars:
    width = bar.get_width()
    ax3.text(width + 0.1,
             bar.get_y() + bar.get_height()/2,
             f'{width:.1f}%',
             ha='left', va='center', fontsize=8)

# 扩大x轴上限(快手最大值更高,+4更保险)
max_quicker = max(quicker_age)
ax3.set_xlim(0, max_quicker + 4)  # 原+2→+4,适配更大的数值标签

ax3.set_title('快手用户年龄分布', fontsize=10)
ax3.set_xlabel('比例(%)', fontsize=9)
ax3.set_yticks(y_age, ages, fontsize=8)

# 调整整体留白(重点增加右侧留白,给下方两图标签留空间)
plt.subplots_adjust(
    left=0.08,
    right=0.97,  # 右侧留白从0.95→0.97,增加右侧空间
    top=0.92,
    bottom=0.15,
    hspace=0.3,
    wspace=0.25  # 增加左右子图间距,避免右侧图标签挤到边缘
)

plt.show()

核心技巧解析

1. 复杂布局设计
python 复制代码
gs = gridspec.GridSpec(2, 2, height_ratios=[1.2, 2], width_ratios=[1, 1])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, 0])
ax3 = fig.add_subplot(gs[1, 1])

gridspec优势:

  • 可以设置不同子图的宽高比例
  • 支持复杂的网格布局
  • 比普通subplots更加灵活
2. 分组柱状图
python 复制代码
bar_width = 0.35
tiktok_bars = ax1.bar(x_city - bar_width/2, tiktok_city, width=bar_width, label='抖音', color='teal')
quicker_bars = ax1.bar(x_city + bar_width/2, quicker_city, width=bar_width, label='快手', color='gold')

分组柱状图技巧:

  • 计算合适的偏移量避免重叠
  • 设置适当的bar_width
  • 使用不同颜色区分组别
3. 水平条形图优化
python 复制代码
tiktok_age_bars = ax2.barh(y_age, tiktok_age, color='teal', height=0.6)

优化点:

  • height=0.6:减小条形高度,避免拥挤
  • 颜色与上方柱状图保持一致,视觉统一
  • 标签位置紧贴条形,减少偏移
4. 坐标轴范围精确控制
python 复制代码
ax2.set_xlim(0, max_tiktok + 3)
ax3.set_xlim(0, max_quicker + 4)

范围设置原则:

  • 确保所有数值标签都能显示
  • 预留适当空间,避免标签超出画布
  • 根据数据最大值动态调整
5. 整体布局微调
python 复制代码
plt.subplots_adjust(
    left=0.08,
    right=0.97,
    top=0.92,
    bottom=0.15,
    hspace=0.3,
    wspace=0.25
)

微调技巧:

  • left/right/top/bottom:控制图形边距
  • hspace/wspace:调整子图间距
  • 根据实际效果逐步调整参数

案例三效果特点

  • 上下布局合理,信息层次清晰
  • 颜色搭配协调(青色代表抖音,金色代表快手)
  • 数据标签位置恰当,不影响图形美观
  • 整体视觉效果专业、美观

综合总结

matplotlib核心技巧

1. 布局设计
  • 简单布局 :使用plt.subplots()创建规则网格
  • 复杂布局 :使用gridspec实现灵活布局
  • 共享轴 :使用sharex/sharey减少重复显示
  • 间距调整 :使用subplots_adjust优化布局
2. 图表类型选择
  • 折线图:适用于时间序列数据
  • 柱状图:适用于类别对比
  • 条形图:适用于类别名称较长的情况
  • 组合图表:适用于多维度数据展示
3. 样式优化
  • 颜色选择:使用鲜明但协调的颜色
  • 线条样式:调整粗细、标记点等
  • 字体设置:合理设置大小和样式
  • 图例添加:清晰标识不同数据系列
4. 数据标注
  • 数值标签:为重要数据点添加标签
  • 标签位置:避免重叠,确保清晰
  • 格式控制:控制小数位数,保持一致性
  • 偏移调整:适当调整位置,提高美观度
5. 坐标轴设置
  • 范围控制:根据数据动态设置范围
  • 刻度设置:合理设置刻度间隔
  • 标签添加:清晰标识坐标轴含义
  • 旋转处理:对于长标签进行适当旋转

最佳实践建议

  1. 数据预处理:确保数据格式正确,缺失值处理恰当
  2. 布局规划:先设计整体布局,再填充细节
  3. 颜色方案:选择2-3种主色调,保持一致性
  4. 字体统一:整个图表使用统一的字体体系
  5. 标签完整:确保所有图表元素都有清晰标识
  6. 测试优化:多次测试,根据效果进行调整
  7. 性能考虑:对于大数据集,考虑性能优化

学习资源推荐

  • 官方文档:matplotlib.org官方文档
  • 在线教程:各种Python数据可视化教程
  • 实践项目:通过实际项目提升技能
  • 社区交流:参与相关社区,学习他人经验

通过这些案例的学习和实践,相信您已经掌握了matplotlib的核心技能。数据可视化是一个不断实践和优化的过程,希望这些技巧能够帮助您创建更加专业、美观的数据图表。


相关推荐
江畔柳前堤6 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore8 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考9 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX10 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面10 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号11 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽11 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI11 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者13 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者13 小时前
【征程6】校准量化中HistogramObserver解析
算法