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

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的核心技能。数据可视化是一个不断实践和优化的过程,希望这些技巧能够帮助您创建更加专业、美观的数据图表。


相关推荐
磊-3 小时前
数组双指针总结
数据结构·算法
.小小陈.4 小时前
链表算法题
数据结构·算法·链表
大飞pkz4 小时前
【算法】排序算法汇总1
开发语言·数据结构·算法·c#·排序算法
前端小L4 小时前
单调栈的“降维打击”:从直方图到矩阵——再探「最大矩形」
数据结构·算法
小丁努力不焦虑4 小时前
c++基本语法
java·c++·算法
货拉拉技术5 小时前
大模型音频水印技术:用AI守护音频数据的“身份指纹”
人工智能·算法·安全
ysa0510305 小时前
利用数的变形简化大规模问题#数论
c++·笔记·算法
CoookeCola5 小时前
开源图像与视频过曝检测工具:HSV色彩空间分析与时序平滑处理技术详解
人工智能·深度学习·算法·目标检测·计算机视觉·开源·音视频
DARLING Zero two♡5 小时前
【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐
java·数据结构·c++·算法·leetcode