【零基础学AI】 第6讲:数据可视化基础

在这里插入图片描述

本节课你将学到

  • 理解数据可视化在AI中的重要作用
  • 掌握Matplotlib的基本架构和核心概念
  • 学会创建各种类型的图表(线图、柱状图、散点图、饼图等)
  • 掌握图表美化和自定义技巧
  • 完成销售趋势图表制作实战项目

开始之前

什么是数据可视化?

数据可视化就是用图形的方式展示数据,让复杂的数字变成直观的视觉信息。想象一下:

  • 纯数字表格:像密密麻麻的账本,信息都在,但很难快速理解
  • 可视化图表:像一张清晰的地图,一眼就能看出规律和趋势

数据可视化的核心价值:

  • 发现规律:肉眼很难从数字中发现的模式,在图表中一目了然
  • 传达洞察:复杂的分析结果通过图表变得容易理解
  • 辅助决策:直观的图表帮助管理者快速做出决策
  • 讲述故事:数据背后的故事通过图表生动地展现出来

为什么Matplotlib重要?

1. Python可视化的基石

  • Matplotlib:Python可视化的底层引擎,功能最全面
  • Seaborn:基于Matplotlib的高级统计图表库
  • Plotly:交互式图表库,底层也参考了Matplotlib设计
  • Pandas:内置的绘图功能就是调用Matplotlib

2. AI项目中的关键应用

  • 数据探索:在建模前理解数据分布和关系
  • 特征分析:可视化特征重要性和相关性
  • 模型评估:绘制ROC曲线、混淆矩阵等
  • 结果展示:将模型预测结果可视化

3. 业界标准

  • 科研论文:大多数机器学习论文的图表都用Matplotlib制作
  • 数据报告:企业级数据分析报告的标准工具
  • 教学演示:AI课程和教程的首选可视化工具

环境要求

  • 已完成前五讲的环境配置
  • Matplotlib已安装(在第1讲中已安装)
  • 建议同时安装Seaborn用于高级图表

Matplotlib基础架构

导入和基本设置

# 标准导入方式
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd# 查看Matplotlib版本
print(f"Matplotlib版本: {plt.matplotlib.__version__}")# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 设置图表样式
plt.style.use('default')  # 可选:'seaborn', 'ggplot', 'classic'等# 设置默认图表大小和分辨率
plt.rcParams['figure.figsize'] = (10, 6)
plt.rcParams['figure.dpi'] = 100print("✅ Matplotlib环境配置完成")

Matplotlib的两种接口

# Matplotlib提供两种编程接口
print("🎨 Matplotlib两种接口演示")
print("=" * 35)# 准备示例数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)# 方式1:pyplot接口(类似MATLAB,简单直观)
print("📊 方式1: pyplot接口")
plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)  # 1行2列的第1个子图
plt.plot(x, y1, label='sin(x)', color='blue', linewidth=2)
plt.plot(x, y2, label='cos(x)', color='red', linewidth=2)
plt.title('Pyplot接口示例')
plt.xlabel('x值')
plt.ylabel('y值')
plt.legend()
plt.grid(True, alpha=0.3)# 方式2:面向对象接口(更灵活,适合复杂图表)
print("🔧 方式2: 面向对象接口")
fig, ax = plt.subplots(1, 1, figsize=(6, 5))  # 创建图形和轴对象ax.plot(x, y1, label='sin(x)', color='blue', linewidth=2)
ax.plot(x, y2, label='cos(x)', color='red', linewidth=2)
ax.set_title('面向对象接口示例')
ax.set_xlabel('x值')
ax.set_ylabel('y值')
ax.legend()
ax.grid(True, alpha=0.3)plt.tight_layout()  # 自动调整子图间距
plt.show()print("💡 建议:简单图表用pyplot,复杂图表用面向对象接口")

Figure和Axes概念

# 理解Figure、Axes、Axis的层次结构
print(f"\n🏗️ Matplotlib架构解析")
print("=" * 30)# Figure: 整个图形窗口
# Axes: 具体的绘图区域(可以有多个)
# Axis: 坐标轴(x轴、y轴)# 创建复杂的图形布局
fig = plt.figure(figsize=(15, 10))
fig.suptitle('Matplotlib架构演示', fontsize=16, fontweight='bold')# 添加多个Axes(子图)
ax1 = fig.add_subplot(2, 3, 1)  # 2行3列的第1个
ax2 = fig.add_subplot(2, 3, 2)  # 2行3列的第2个
ax3 = fig.add_subplot(2, 3, 3)  # 2行3列的第3个
ax4 = fig.add_subplot(2, 1, 2)  # 2行1列的第2个(占据下半部分)# 在每个Axes中绘制不同类型的图表
# 子图1:线图
x = np.linspace(0, 10, 50)
ax1.plot(x, np.sin(x), 'b-', linewidth=2, label='sin(x)')
ax1.set_title('线图示例')
ax1.set_xlabel('x')
ax1.set_ylabel('sin(x)')
ax1.legend()
ax1.grid(True, alpha=0.3)# 子图2:散点图
np.random.seed(42)
x_scatter = np.random.randn(50)
y_scatter = np.random.randn(50)
colors = np.random.rand(50)
ax2.scatter(x_scatter, y_scatter, c=colors, alpha=0.6, s=60)
ax2.set_title('散点图示例')
ax2.set_xlabel('X值')
ax2.set_ylabel('Y值')# 子图3:柱状图
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]
bars = ax3.bar(categories, values, color=['red', 'green', 'blue', 'orange', 'purple'])
ax3.set_title('柱状图示例')
ax3.set_xlabel('类别')
ax3.set_ylabel('数值')# 在柱状图上添加数值标签
for bar, value in zip(bars, values):ax3.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1,str(value), ha='center', va='bottom')# 子图4:多系列折线图
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
sales_2023 = [120, 135, 148, 162, 151, 178]
sales_2024 = [125, 142, 156, 169, 163, 185]ax4.plot(months, sales_2023, marker='o', linewidth=2, label='2023年销售')
ax4.plot(months, sales_2024, marker='s', linewidth=2, label='2024年销售')
ax4.set_title('月度销售对比')
ax4.set_xlabel('月份')
ax4.set_ylabel('销售额(万元)')
ax4.legend()
ax4.grid(True, alpha=0.3)plt.tight_layout()
plt.show()print("📋 架构总结:")
print("  - Figure: 整个图形画布")
print("  - Axes: 各个子图区域") 
print("  - Axis: x轴、y轴等坐标轴")
print("  - Artists: 所有可见元素(线条、文字、图例等)")

基本图表类型

线图(Line Plot)

# 线图详解和应用
print(f"\n📈 线图详解")
print("=" * 20)# 创建示例数据
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
temperature = [2, 4, 8, 14, 20, 25, 28, 27, 22, 16, 9, 4]  # 某城市月平均气温
rainfall = [45, 38, 52, 61, 75, 89, 102, 95, 78, 67, 55, 48]  # 月降雨量fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 6))# 基础线图
ax1.plot(months, temperature, color='red', linewidth=2, marker='o', markersize=6)
ax1.set_title('月平均气温变化', fontsize=14, fontweight='bold')
ax1.set_xlabel('月份')
ax1.set_ylabel('温度 (°C)')
ax1.grid(True, alpha=0.3)
ax1.tick_params(axis='x', rotation=45)# 多系列线图
ax2.plot(months, temperature, color='red', linewidth=2, marker='o', markersize=6, label='气温 (°C)')
ax2_twin = ax2.twinx()  # 创建共享x轴的第二个y轴
ax2_twin.plot(months, rainfall, color='blue', linewidth=2, marker='s', markersize=6, label='降雨量 (mm)')ax2.set_title('气温与降雨量变化', fontsize=14, fontweight='bold')
ax2.set_xlabel('月份')
ax2.set_ylabel('温度 (°C)', color='red')
ax2_twin.set_ylabel('降雨量 (mm)', color='blue')
ax2.tick_params(axis='x', rotation=45)
ax2.tick_params(axis='y', labelcolor='red')
ax2_twin.tick_params(axis='y', labelcolor='blue')# 组合图例
lines1, labels1 = ax2.get_legend_handles_labels()
lines2, labels2 = ax2_twin.get_legend_handles_labels()
ax2.legend(lines1 + lines2, labels1 + labels2, loc='upper left')# 线型样式展示
x = np.linspace(0, 10, 20)
ax3.plot(x, np.sin(x), '-', label='实线 solid', linewidth=2)
ax3.plot(x, np.sin(x + 0.5), '--', label='虚线 dashed', linewidth=2)
ax3.plot(x, np.sin(x + 1), '-.', label='点划线 dashdot', linewidth=2)
ax3.plot(x, np.sin(x + 1.5), ':', label='点线 dotted', linewidth=2)ax3.set_title('线型样式展示', fontsize=14, fontweight='bold')
ax3.set_xlabel('x值')
ax3.set_ylabel('y值')
ax3.legend()
ax3.grid(True, alpha=0.3)plt.tight_layout()
plt.show()print("📝 线图使用场景:")
print("  - 时间序列数据(股价、气温、销售趋势等)")
print("  - 连续变量关系(函数图像、回归线等)")
print("  - 多组数据对比(不同年份、不同产品等)")

柱状图(Bar Plot)

# 柱状图详解
print(f"\n📊 柱状图详解")
print("=" * 20)# 准备数据
products = ['iPhone', 'Samsung', 'Huawei', 'Xiaomi', 'OPPO']
q1_sales = [45, 38, 25, 22, 18]
q2_sales = [48, 35, 28, 25, 20]
q3_sales = [52, 40, 30, 28, 22]fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))# 1. 基础柱状图
bars1 = ax1.bar(products, q1_sales, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'])
ax1.set_title('Q1销售额(单位:万台)', fontsize=14, fontweight='bold')
ax1.set_xlabel('品牌')
ax1.set_ylabel('销售额')# 添加数值标签
for bar, value in zip(bars1, q1_sales):ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5,f'{value}万', ha='center', va='bottom', fontweight='bold')# 2. 分组柱状图
x = np.arange(len(products))  # 标签位置
width = 0.25  # 柱子宽度bars2_1 = ax2.bar(x - width, q1_sales, width, label='Q1', color='#FF6B6B', alpha=0.8)
bars2_2 = ax2.bar(x, q2_sales, width, label='Q2', color='#4ECDC4', alpha=0.8)
bars2_3 = ax2.bar(x + width, q3_sales, width, label='Q3', color='#45B7D1', alpha=0.8)ax2.set_title('季度销售对比', fontsize=14, fontweight='bold')
ax2.set_xlabel('品牌')
ax2.set_ylabel('销售额(万台)')
ax2.set_xticks(x)
ax2.set_xticklabels(products)
ax2.legend()# 3. 堆叠柱状图
ax3.bar(products, q1_sales, label='Q1', color='#FF6B6B', alpha=0.8)
ax3.bar(products, q2_sales, bottom=q1_sales, label='Q2', color='#4ECDC4', alpha=0.8)# 计算Q3的底部位置
q3_bottom = [q1 + q2 for q1, q2 in zip(q1_sales, q2_sales)]
ax3.bar(products, q3_sales, bottom=q3_bottom, label='Q3', color='#45B7D1', alpha=0.8)ax3.set_title('累计销售额', fontsize=14, fontweight='bold')
ax3.set_xlabel('品牌')
ax3.set_ylabel('累计销售额(万台)')
ax3.legend()# 4. 水平柱状图
ax4.barh(products, q1_sales, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'])
ax4.set_title('Q1销售额(水平)', fontsize=14, fontweight='bold')
ax4.set_xlabel('销售额(万台)')
ax4.set_ylabel('品牌')# 添加数值标签
for i, value in enumerate(q1_sales):ax4.text(value + 0.5, i, f'{value}万', va='center', fontweight='bold')plt.tight_layout()
plt.show()print("📝 柱状图使用场景:")
print("  - 分类数据比较(销售额、人口、得分等)")
print("  - 频次分布(直方图的离散版本)")
print("  - 多组数据对比(分组柱状图)")
print("  - 部分与整体关系(堆叠柱状图)")

散点图(Scatter Plot)

# 散点图详解
print(f"\n🔹 散点图详解")
print("=" * 20)# 生成示例数据
np.random.seed(42)
n_points = 100# 数据集1:身高体重关系
height = np.random.normal(170, 10, n_points)  # 身高(cm)
weight = 0.8 * height + np.random.normal(0, 5, n_points) - 80  # 体重(kg)
gender = np.random.choice(['男', '女'], n_points)# 数据集2:广告投入与销售额
ad_spend = np.random.uniform(10, 100, n_points)  # 广告投入(万元)
sales = 2 * ad_spend + np.random.normal(0, 15, n_points) + 50  # 销售额(万元)
region = np.random.choice(['北区', '南区', '东区', '西区'], n_points)fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))# 1. 基础散点图
ax1.scatter(height, weight, alpha=0.6, s=50, color='blue')
ax1.set_title('身高与体重关系', fontsize=14, fontweight='bold')
ax1.set_xlabel('身高 (cm)')
ax1.set_ylabel('体重 (kg)')
ax1.grid(True, alpha=0.3)# 添加趋势线
z = np.polyfit(height, weight, 1)  # 一次线性拟合
p = np.poly1d(z)
ax1.plot(height, p(height), "r--", alpha=0.8, linewidth=2, label=f'趋势线: y={z[0]:.2f}x{z[1]:+.2f}')
ax1.legend()# 2. 分类散点图(不同颜色表示不同类别)
colors = {'男': 'blue', '女': 'red'}
for g in ['男', '女']:mask = gender == gax2.scatter(height[mask], weight[mask], c=colors[g], label=g, alpha=0.6, s=50)ax2.set_title('按性别分类的身高体重关系', fontsize=14, fontweight='bold')
ax2.set_xlabel('身高 (cm)')
ax2.set_ylabel('体重 (kg)')
ax2.legend()
ax2.grid(True, alpha=0.3)# 3. 大小和颜色映射
# 点的大小表示销售额,颜色表示地区
region_colors = {'北区': 'red', '南区': 'green', '东区': 'blue', '西区': 'orange'}
for r in ['北区', '南区', '东区', '西区']:mask = region == rax3.scatter(ad_spend[mask], sales[mask], c=region_colors[r], label=r, alpha=0.6, s=sales[mask]*2)  # 点的大小与销售额成正比ax3.set_title('广告投入与销售额关系\n(点大小=销售额,颜色=地区)', fontsize=14, fontweight='bold')
ax3.set_xlabel('广告投入 (万元)')
ax3.set_ylabel('销售额 (万元)')
ax3.legend()
ax3.grid(True, alpha=0.3)# 4. 气泡图(三维数据的二维展示)
# 第三个维度用颜色和大小表示
profit_margin = np.random.uniform(0.1, 0.3, n_points)  # 利润率scatter = ax4.scatter(ad_spend, sales, c=profit_margin, s=profit_margin*1000, alpha=0.6, cmap='viridis')ax4.set_title('广告投入、销售额与利润率关系\n(颜色和大小=利润率)', fontsize=14, fontweight='bold')
ax4.set_xlabel('广告投入 (万元)')
ax4.set_ylabel('销售额 (万元)')# 添加颜色条
cbar = plt.colorbar(scatter, ax=ax4)
cbar.set_label('利润率', rotation=270, labelpad=20)plt.tight_layout()
plt.show()print("📝 散点图使用场景:")
print("  - 两个连续变量关系(相关性分析)")
print("  - 异常值检测(离群点识别)")
print("  - 聚类结果展示(不同颜色表示不同类别)")
print("  - 三维数据降维展示(颜色或大小表示第三维)")

饼图(Pie Chart)

# 饼图详解
print(f"\n🥧 饼图详解")
print("=" * 15)# 准备数据
market_share = {'Android': 71.9,'iOS': 27.3,'Others': 0.8
}sales_by_region = {'华东': 35,'华南': 28,'华北': 22,'华中': 10,'其他': 5
}fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))# 1. 基础饼图
labels1 = list(market_share.keys())
sizes1 = list(market_share.values())
colors1 = ['#FF9999', '#66B2FF', '#99FF99']wedges1, texts1, autotexts1 = ax1.pie(sizes1, labels=labels1, colors=colors1, autopct='%1.1f%%', startangle=90)ax1.set_title('全球移动操作系统市场份额', fontsize=14, fontweight='bold')# 美化文字
for autotext in autotexts1:autotext.set_color('white')autotext.set_fontweight('bold')# 2. 突出显示饼图
labels2 = list(sales_by_region.keys())
sizes2 = list(sales_by_region.values())
colors2 = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
explode2 = (0.1, 0, 0, 0, 0)  # 突出显示第一个扇形wedges2, texts2, autotexts2 = ax2.pie(sizes2, labels=labels2, colors=colors2,autopct='%1.1f%%', startangle=90,explode=explode2, shadow=True)ax2.set_title('各地区销售额分布', fontsize=14, fontweight='bold')# 3. 环形图(甜甜圈图)
wedges3, texts3, autotexts3 = ax3.pie(sizes2, labels=labels2, colors=colors2,autopct='%1.1f%%', startangle=90,wedgeprops=dict(width=0.5))ax3.set_title('各地区销售额分布(环形图)', fontsize=14, fontweight='bold')# 在中心添加总计信息
total_sales = sum(sizes2)
ax3.text(0, 0, f'总销售额\n{total_sales}%', ha='center', va='center',fontsize=12, fontweight='bold')# 4. 嵌套饼图
# 外环:大类别
outer_labels = ['移动设备', '电脑设备']
outer_sizes = [75, 25]
outer_colors = ['#FF6B6B', '#4ECDC4']# 内环:细分类别
inner_labels = ['手机', '平板', '笔记本', '台式机']
inner_sizes = [50, 25, 15, 10]
inner_colors = ['#FF9999', '#FFB366', '#66B2FF', '#99CCFF']# 绘制外环
ax4.pie(outer_sizes, labels=outer_labels, colors=outer_colors,radius=1, startangle=90, labeldistance=1.1)# 绘制内环
ax4.pie(inner_sizes, labels=inner_labels, colors=inner_colors,radius=0.7, startangle=90, labeldistance=0.5)ax4.set_title('设备销售额嵌套分布', fontsize=14, fontweight='bold')plt.tight_layout()
plt.show()print("📝 饼图使用场景:")
print("  - 部分与整体的比例关系")
print("  - 分类数据的占比展示")
print("  - 市场份额、预算分配等")
print("  ⚠️  注意:类别过多时不适用(建议不超过7个)")

直方图(Histogram)

# 直方图详解
print(f"\n📊 直方图详解")
print("=" * 20)# 生成示例数据
np.random.seed(42)
normal_data = np.random.normal(100, 15, 1000)  # 正态分布数据
uniform_data = np.random.uniform(50, 150, 1000)  # 均匀分布数据
exponential_data = np.random.exponential(2, 1000)  # 指数分布数据# 学生成绩数据(更真实的例子)
math_scores = np.random.normal(75, 12, 200)
english_scores = np.random.normal(78, 10, 200)fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))# 1. 基础直方图
ax1.hist(normal_data, bins=30, color='skyblue', alpha=0.7, edgecolor='black')
ax1.set_title('正态分布数据直方图', fontsize=14, fontweight='bold')
ax1.set_xlabel('数值')
ax1.set_ylabel('频次')
ax1.axvline(normal_data.mean(), color='red', linestyle='--', label=f'均值: {normal_data.mean():.1f}')
ax1.legend()
ax1.grid(True, alpha=0.3)# 2. 多组数据对比
ax2.hist(math_scores, bins=20, alpha=0.7, label='数学成绩', color='blue')
ax2.hist(english_scores, bins=20, alpha=0.7, label='英语成绩', color='red')
ax2.set_title('数学与英语成绩分布对比', fontsize=14, fontweight='bold')
ax2.set_xlabel('成绩')
ax2.set_ylabel('人数')
ax2.legend()
ax2.grid(True, alpha=0.3)# 3. 不同分布类型对比
ax3.hist(normal_data, bins=30, alpha=0.5, label='正态分布', density=True)
ax3.hist(uniform_data, bins=30, alpha=0.5, label='均匀分布', density=True)
ax3.set_title('不同分布类型对比(密度)', fontsize=14, fontweight='bold')
ax3.set_xlabel('数值')
ax3.set_ylabel('密度')
ax3.legend()
ax3.grid(True, alpha=0.3)# 4. 累积直方图
counts, bins, patches = ax4.hist(math_scores, bins=20, cumulative=True, alpha=0.7, color='green', edgecolor='black')
ax4.set_title('数学成绩累积分布', fontsize=14, fontweight='bold')
ax4.set_xlabel('成绩')
ax4.set_ylabel('累积人数')# 添加百分位线
percentiles = [25, 50, 75]
for p in percentiles:value = np.percentile(math_scores, p)ax4.axvline(value, color='red', linestyle='--', alpha=0.7)ax4.text(value, ax4.get_ylim()[1]*0.9, f'{p}th', ha='center', va='bottom', color='red', fontweight='bold')ax4.grid(True, alpha=0.3)plt.tight_layout()
plt.show()print("📝 直方图使用场景:")
print("  - 数据分布形状分析(正态、偏态、双峰等)")
print("  - 异常值检测(分布的尾部)")
print("  - 质量控制(过程能力分析)")
print("  - A/B测试结果比较")

图表美化和自定义

颜色和样式设置

# 图表美化技巧
print(f"\n🎨 图表美化技巧")
print("=" * 25)# 准备数据
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
revenue = [120, 135, 128, 142, 156, 168]
profit = [24, 28, 25, 30, 35, 38]fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))# 1. 默认样式 vs 美化样式对比
# 默认样式
ax1.plot(months, revenue, label='收入')
ax1.plot(months, profit, label='利润')
ax1.set_title('默认样式')
ax1.legend()# 美化样式
ax2.plot(months, revenue, color='#2E86AB', linewidth=3, marker='o', markersize=8, markerfacecolor='white', markeredgewidth=2,markeredgecolor='#2E86AB', label='收入')
ax2.plot(months, profit, color='#A23B72', linewidth=3, marker='s', markersize=8, markerfacecolor='white', markeredgewidth=2,markeredgecolor='#A23B72', label='利润')ax2.set_title('美化样式', fontsize=16, fontweight='bold', pad=20)
ax2.set_xlabel('月份', fontsize=12, fontweight='bold')
ax2.set_ylabel('金额(万元)', fontsize=12, fontweight='bold')
ax2.legend(frameon=True, fancybox=True, shadow=True, fontsize=11)
ax2.grid(True, alpha=0.3, linestyle='--')
ax2.set_facecolor('#f8f9fa')  # 设置背景色# 3. 颜色映射和渐变
x = np.linspace(0, 10, 100)
y = np.sin(x)
colors = plt.cm.viridis(np.linspace(0, 1, len(x)))  # 使用颜色映射for i in range(len(x)-1):ax3.plot(x[i:i+2], y[i:i+2], color=colors[i], linewidth=3)ax3.set_title('颜色渐变效果', fontsize=14, fontweight='bold')
ax3.set_xlabel('x值')
ax3.set_ylabel('sin(x)')
ax3.grid(True, alpha=0.3)# 4. 高级样式设置
# 创建专业的财务图表
ax4.plot(months, revenue, color='#1f77b4', linewidth=4, marker='o', markersize=10, label='月收入', zorder=3)# 添加填充区域
ax4.fill_between(months, revenue, alpha=0.3, color='#1f77b4')# 添加注释
max_revenue_idx = np.argmax(revenue)
ax4.annotate(f'最高收入\n{revenue[max_revenue_idx]}万元', xy=(months[max_revenue_idx], revenue[max_revenue_idx]),xytext=(max_revenue_idx+0.5, revenue[max_revenue_idx]+10),arrowprops=dict(arrowstyle='->', color='red', lw=2),fontsize=12, fontweight='bold',bbox=dict(boxstyle="round,pad=0.3", facecolor='yellow', alpha=0.7))# 设置坐标轴样式
ax4.spines['top'].set_visible(False)     # 隐藏上边框
ax4.spines['right'].set_visible(False)   # 隐藏右边框
ax4.spines['left'].set_linewidth(2)      # 加粗左边框
ax4.spines['bottom'].set_linewidth(2)    # 加粗下边框ax4.set_title('专业财务图表样式', fontsize=14, fontweight='bold')
ax4.set_xlabel('月份', fontsize=12)
ax4.set_ylabel('收入(万元)', fontsize=12)
ax4.grid(True, alpha=0.3, axis='y')plt.tight_layout()
plt.show()print("🎨 美化技巧总结:")
print("  - 选择协调的颜色搭配")
print("  - 适当使用透明度和阴影")
print("  - 添加网格线但保持低调")
print("  - 使用注释突出重点信息")
print("  - 简化边框,突出数据本身")

子图和布局

# 复杂布局和子图管理
print(f"\n📐 复杂布局设计")
print("=" * 25)# 创建综合分析仪表板
fig = plt.figure(figsize=(20, 12))# 定义网格布局
gs = fig.add_gridspec(3, 4, hspace=0.3, wspace=0.3)# 准备各种示例数据
np.random.seed(42)
time_data = pd.date_range('2024-01-01', periods=365, freq='D')
daily_sales = np.random.normal(1000, 200, 365) + 100 * np.sin(np.arange(365) * 2 * np.pi / 365)categories = ['A', 'B', 'C', 'D', 'E']
category_values = [45, 38, 32, 28, 22]regions = ['北区', '南区', '东区', '西区']
region_data = np.random.rand(4, 6) * 100# 1. 主要趋势图(占据两行)
ax_main = fig.add_subplot(gs[0:2, 0:2])
ax_main.plot(time_data, daily_sales, color='#1f77b4', linewidth=1.5, alpha=0.8)# 添加移动平均线
window = 30
rolling_mean = pd.Series(daily_sales).rolling(window=window).mean()
ax_main.plot(time_data, rolling_mean, color='red', linewidth=3, label=f'{window}天移动平均')ax_main.set_title('年度销售趋势分析', fontsize=16, fontweight='bold')
ax_main.set_xlabel('日期')
ax_main.set_ylabel('销售额')
ax_main.legend()
ax_main.grid(True, alpha=0.3)# 2. 分类分析饼图
ax_pie = fig.add_subplot(gs[0, 2])
wedges, texts, autotexts = ax_pie.pie(category_values, labels=categories, autopct='%1.1f%%', startangle=90)
ax_pie.set_title('产品类别分布', fontsize=12, fontweight='bold')# 3. 地区对比柱状图
ax_bar = fig.add_subplot(gs[0, 3])
bars = ax_bar.bar(regions, [sum(region_data[i]) for i in range(4)], color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'])
ax_bar.set_title('各地区销售总额', fontsize=12, fontweight='bold')
ax_bar.set_ylabel('销售额')# 添加数值标签
for bar in bars:height = bar.get_height()ax_bar.text(bar.get_x() + bar.get_width()/2., height + 5,f'{height:.0f}', ha='center', va='bottom')# 4. 热力图
ax_heatmap = fig.add_subplot(gs[1, 2:4])
im = ax_heatmap.imshow(region_data, cmap='YlOrRd', aspect='auto')# 设置坐标轴标签
ax_heatmap.set_xticks(range(6))
ax_heatmap.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'])
ax_heatmap.set_yticks(range(4))
ax_heatmap.set_yticklabels(regions)
ax_heatmap.set_title('地区月度销售热力图', fontsize=12, fontweight='bold')# 添加数值标注
for i in range(4):for j in range(6):text = ax_heatmap.text(j, i, f'{region_data[i, j]:.0f}',ha="center", va="center", color="black", fontsize=8)# 添加颜色条
cbar = plt.colorbar(im, ax=ax_heatmap, shrink=0.8)
cbar.set_label('销售额', rotation=270, labelpad=15)# 5. 分布分析直方图
ax_hist = fig.add_subplot(gs[2, 0])
ax_hist.hist(daily_sales, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
ax_hist.set_title('销售额分布', fontsize=12, fontweight='bold')
ax_hist.set_xlabel('销售额')
ax_hist.set_ylabel('天数')
ax_hist.axvline(np.mean(daily_sales), color='red', linestyle='--', label=f'均值: {np.mean(daily_sales):.0f}')
ax_hist.legend()# 6. 相关性散点图
ax_scatter = fig.add_subplot(gs[2, 1])
x_corr = np.random.normal(50, 15, 100)
y_corr = 0.7 * x_corr + np.random.normal(0, 10, 100)
ax_scatter.scatter(x_corr, y_corr, alpha=0.6, s=50)# 添加趋势线
z = np.polyfit(x_corr, y_corr, 1)
p = np.poly1d(z)
ax_scatter.plot(x_corr, p(x_corr), "r--", alpha=0.8)ax_scatter.set_title('销售额与广告投入相关性', fontsize=12, fontweight='bold')
ax_scatter.set_xlabel('广告投入')
ax_scatter.set_ylabel('销售额')
ax_scatter.grid(True, alpha=0.3)# 7. 箱线图
ax_box = fig.add_subplot(gs[2, 2])
box_data = [np.random.normal(0, std, 100) for std in range(1, 5)]
bp = ax_box.boxplot(box_data, labels=['Q1', 'Q2', 'Q3', 'Q4'], patch_artist=True)colors = ['lightblue', 'lightgreen', 'lightyellow', 'lightcoral']
for patch, color in zip(bp['boxes'], colors):patch.set_facecolor(color)ax_box.set_title('季度销售分布', fontsize=12, fontweight='bold')
ax_box.set_ylabel('销售额变化率')# 8. 综合统计表格
ax_table = fig.add_subplot(gs[2, 3])
ax_table.axis('tight')
ax_table.axis('off')# 创建统计表格
stats_data = [['指标', '数值'],['总销售额', f'{sum(daily_sales):.0f}万'],['平均日销售', f'{np.mean(daily_sales):.0f}万'],['最高日销售', f'{max(daily_sales):.0f}万'],['销售天数', f'{len(daily_sales)}天'],['增长率', '+15.3%']
]table = ax_table.table(cellText=stats_data, cellLoc='center', loc='center',colWidths=[0.4, 0.4])
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1, 2)# 设置表格样式
for i in range(len(stats_data)):if i == 0:  # 标题行for j in range(2):table[(i, j)].set_facecolor('#4CAF50')table[(i, j)].set_text_props(weight='bold', color='white')else:for j in range(2):table[(i, j)].set_facecolor('#f0f0f0' if i % 2 == 0 else '#ffffff')ax_table.set_title('关键指标汇总', fontsize=12, fontweight='bold')# 添加总标题
fig.suptitle('销售数据综合分析仪表板', fontsize=20, fontweight='bold', y=0.98)plt.show()print("📊 复杂布局设计要点:")
print("  - 使用GridSpec进行精确布局控制")
print("  - 主要图表占据更大空间")
print("  - 保持视觉平衡和逻辑关系")
print("  - 统一色彩主题和字体样式")
print("  - 添加总标题增强整体性")

完整项目:销售趋势图表制作

让我们创建一个完整的销售趋势分析项目:

# sales_visualization.py - 销售趋势图表制作项目
"""
使用Matplotlib创建专业的销售趋势分析图表
演示数据可视化在业务分析中的应用
"""import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
import seaborn as snsclass SalesVisualizationManager:"""销售数据可视化管理器"""def __init__(self):"""初始化可视化管理器"""# 设置中文字体和样式plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']plt.rcParams['axes.unicode_minus'] = Falseplt.rcParams['figure.dpi'] = 100# 定义统一的颜色主题self.colors = {'primary': '#2E86AB','secondary': '#A23B72', 'success': '#4CAF50','warning': '#FF9800','danger': '#F44336','info': '#2196F3','light': '#F5F5F5','dark': '#333333'}# 设置默认样式plt.style.use('default')print("📊 销售数据可视化管理器初始化完成")def generate_sales_data(self, start_date='2023-01-01', days=365):"""生成模拟销售数据参数:start_date: 开始日期days: 生成天数"""print(f"🎲 生成 {days} 天的销售数据...")np.random.seed(42)# 生成日期序列date_range = pd.date_range(start=start_date, periods=days, freq='D')# 产品和地区信息products = ['iPhone', 'iPad', 'MacBook', 'AirPods', 'Apple Watch']regions = ['华东', '华南', '华北', '华中', '西部']records = []for date in date_range:for product in products:for region in regions:# 基础销售额(不同产品有不同基准)base_prices = {'iPhone': 5000, 'iPad': 3000, 'MacBook': 8000,'AirPods': 1500, 'Apple Watch': 2500}# 季节性因子day_of_year = date.timetuple().tm_ydayseasonal_factor = 1 + 0.3 * np.sin(2 * np.pi * day_of_year / 365)# 周末效应weekend_factor = 0.8 if date.weekday() >= 5 else 1.0# 地区系数region_factors = {'华东': 1.3, '华南': 1.2, '华北': 1.1, '华中': 0.9, '西部': 0.8}# 计算销售额base_sales = base_prices[product]daily_sales = (base_sales * seasonal_factor * weekend_factor * region_factors[region] * np.random.normal(1, 0.2))# 确保为正数daily_sales = max(daily_sales, base_sales * 0.3)# 计算销售数量quantity = max(1, int(daily_sales / (base_sales * 0.8) + np.random.normal(0, 0.5)))records.append({'Date': date,'Product': product,'Region': region,'Sales': round(daily_sales, 2),'Quantity': quantity,'Month': date.month,'Quarter': (date.month - 1) // 3 + 1,'Weekday': date.strftime('%A'),'IsWeekend': date.weekday() >= 5})self.sales_data = pd.DataFrame(records)print(f"✅ 销售数据生成完成,共 {len(self.sales_data)} 条记录")return self.sales_datadef create_time_series_charts(self):"""创建时间序列分析图表"""print("📈 创建时间序列分析图表...")# 准备时间序列数据daily_sales = self.sales_data.groupby('Date')['Sales'].sum().reset_index()monthly_sales = self.sales_data.groupby(self.sales_data['Date'].dt.to_period('M'))['Sales'].sum()weekly_sales = self.sales_data.groupby(self.sales_data['Date'].dt.to_period('W'))['Sales'].sum()fig, axes = plt.subplots(2, 2, figsize=(20, 12))fig.suptitle('销售趋势时间序列分析', fontsize=18, fontweight='bold')# 1. 日销售趋势ax1 = axes[0, 0]ax1.plot(daily_sales['Date'], daily_sales['Sales'], color=self.colors['primary'], linewidth=1, alpha=0.7)# 添加7天移动平均线daily_sales['MA7'] = daily_sales['Sales'].rolling(window=7).mean()ax1.plot(daily_sales['Date'], daily_sales['MA7'], color=self.colors['danger'], linewidth=3, label='7天移动平均')# 添加30天移动平均线daily_sales['MA30'] = daily_sales['Sales'].rolling(window=30).mean()ax1.plot(daily_sales['Date'], daily_sales['MA30'], color=self.colors['success'], linewidth=3, label='30天移动平均')ax1.set_title('日销售额趋势', fontsize=14, fontweight='bold')ax1.set_xlabel('日期')ax1.set_ylabel('销售额(元)')ax1.legend()ax1.grid(True, alpha=0.3)# 2. 月度销售趋势ax2 = axes[0, 1]bars = ax2.bar(range(len(monthly_sales)), monthly_sales.values, color=self.colors['info'], alpha=0.8)# 添加趋势线x_trend = range(len(monthly_sales))z = np.polyfit(x_trend, monthly_sales.values, 1)p = np.poly1d(z)ax2.plot(x_trend, p(x_trend), color=self.colors['danger'], linewidth=3, linestyle='--', label='趋势线')ax2.set_title('月度销售额趋势', fontsize=14, fontweight='bold')ax2.set_xlabel('月份')ax2.set_ylabel('销售额(元)')ax2.set_xticks(range(len(monthly_sales)))ax2.set_xticklabels([str(period) for period in monthly_sales.index], rotation=45)ax2.legend()# 添加数值标签for i, bar in enumerate(bars):height = bar.get_height()ax2.text(bar.get_x() + bar.get_width()/2., height + height*0.01,f'{height/10000:.0f}万', ha='center', va='bottom', fontsize=9)# 3. 周度销售趋势ax3 = axes[1, 0]ax3.plot(range(len(weekly_sales)), weekly_sales.values, marker='o', markersize=4, color=self.colors['secondary'], linewidth=2, markerfacecolor='white', markeredgewidth=2)ax3.set_title('周销售额趋势', fontsize=14, fontweight='bold')ax3.set_xlabel('周数')ax3.set_ylabel('销售额(元)')ax3.grid(True, alpha=0.3)# 4. 季节性分析ax4 = axes[1, 1]# 按月份统计平均销售额monthly_avg = self.sales_data.groupby('Month')['Sales'].mean()# 创建极坐标图显示季节性theta = np.linspace(0, 2*np.pi, 12)r = monthly_avg.values# 闭合曲线theta = np.concatenate([theta, [theta[0]]])r = np.concatenate([r, [r[0]]])ax4.plot(theta, r, color=self.colors['warning'], linewidth=3, marker='o')ax4.fill(theta, r, alpha=0.3, color=self.colors['warning'])ax4.set_thetagrids(np.arange(0, 360, 30), ['1月', '2月', '3月', '4月', '5月', '6月','7月', '8月', '9月', '10月', '11月', '12月'])ax4.set_title('月度销售季节性分析(极坐标)', fontsize=14, fontweight='bold')plt.tight_layout()plt.show()print("✅ 时间序列图表创建完成")def create_product_analysis_charts(self):"""创建产品分析图表"""print("📱 创建产品分析图表...")fig, axes = plt.subplots(2, 2, figsize=(18, 12))fig.suptitle('产品销售分析', fontsize=18, fontweight='bold')# 1. 产品销售额对比ax1 = axes[0, 0]product_sales = self.sales_data.groupby('Product')['Sales'].sum().sort_values(ascending=False)bars = ax1.bar(product_sales.index, product_sales.values, color=[self.colors['primary'], self.colors['secondary'], self.colors['success'], self.colors['warning'], self.colors['info']])ax1.set_title('各产品销售额对比', fontsize=14, fontweight='bold')ax1.set_xlabel('产品')ax1.set_ylabel('销售额(元)')ax1.tick_params(axis='x', rotation=45)# 添加数值标签和百分比total_sales = product_sales.sum()for i, (bar, value) in enumerate(zip(bars, product_sales.values)):percentage = value / total_sales * 100ax1.text(bar.get_x() + bar.get_width()/2., bar.get_height() + value*0.01,f'{value/10000:.0f}万\n({percentage:.1f}%)', ha='center', va='bottom', fontweight='bold')# 2. 产品市场份额饼图ax2 = axes[0, 1]colors = [self.colors['primary'], self.colors['secondary'], self.colors['success'], self.colors['warning'], self.colors['info']]wedges, texts, autotexts = ax2.pie(product_sales.values, labels=product_sales.index,colors=colors, autopct='%1.1f%%', startangle=90,explode=(0.05, 0, 0, 0, 0))  # 突出最大份额ax2.set_title('产品市场份额分布', fontsize=14, fontweight='bold')# 美化饼图文字for autotext in autotexts:autotext.set_color('white')autotext.set_fontweight('bold')autotext.set_fontsize(10)# 3. 产品月度趋势对比ax3 = axes[1, 0]product_monthly = self.sales_data.groupby(['Month', 'Product'])['Sales'].sum().unstack()for i, product in enumerate(product_monthly.columns):ax3.plot(product_monthly.index, product_monthly[product], marker='o', linewidth=2, label=product, color=colors[i])ax3.set_title('各产品月度销售趋势', fontsize=14, fontweight='bold')ax3.set_xlabel('月份')ax3.set_ylabel('销售额(元)')ax3.legend(bbox_to_anchor=(1.05, 1), loc='upper left')ax3.grid(True, alpha=0.3)# 4. 产品销售数量与金额关系ax4 = axes[1, 1]product_stats = self.sales_data.groupby('Product').agg({'Sales': 'sum','Quantity': 'sum'}).reset_index()# 计算平均单价product_stats['AvgPrice'] = product_stats['Sales'] / product_stats['Quantity']# 气泡图:x=数量,y=销售额,大小=平均单价scatter = ax4.scatter(product_stats['Quantity'], product_stats['Sales'],s=product_stats['AvgPrice']/10, alpha=0.6,c=range(len(product_stats)), cmap='viridis')# 添加产品名称标注for i, row in product_stats.iterrows():ax4.annotate(row['Product'], (row['Quantity'], row['Sales']),xytext=(5, 5), textcoords='offset points',fontweight='bold')ax4.set_title('产品销售数量vs金额关系\n(气泡大小=平均单价)', fontsize=14, fontweight='bold')ax4.set_xlabel('销售数量')ax4.set_ylabel('销售额(元)')ax4.grid(True, alpha=0.3)plt.tight_layout()plt.show()print("✅ 产品分析图表创建完成")def create_regional_analysis_charts(self):"""创建地区分析图表"""print("🗺️ 创建地区分析图表...")fig, axes = plt.subplots(2, 2, figsize=(18, 12))fig.suptitle('地区销售分析', fontsize=18, fontweight='bold')# 1. 地区销售额对比ax1 = axes[0, 0]region_sales = self.sales_data.groupby('Region')['Sales'].sum().sort_values(ascending=True)bars = ax1.barh(region_sales.index, region_sales.values,color=self.colors['primary'])ax1.set_title('各地区销售额对比', fontsize=14, fontweight='bold')ax1.set_xlabel('销售额(元)')ax1.set_ylabel('地区')# 添加数值标签for i, (bar, value) in enumerate(zip(bars, region_sales.values)):ax1.text(bar.get_width() + value*0.01, bar.get_y() + bar.get_height()/2,f'{value/10000:.0f}万', va='center', fontweight='bold')# 2. 地区产品组合热力图ax2 = axes[0, 1]region_product = self.sales_data.groupby(['Region', 'Product'])['Sales'].sum().unstack()# 标准化数据以便比较region_product_norm = region_product.div(region_product.sum(axis=1), axis=0)im = ax2.imshow(region_product_norm.values, cmap='YlOrRd', aspect='auto')# 设置坐标轴ax2.set_xticks(range(len(region_product_norm.columns)))ax2.set_xticklabels(region_product_norm.columns, rotation=45)ax2.set_yticks(range(len(region_product_norm.index)))ax2.set_yticklabels(region_product_norm.index)ax2.set_title('地区产品组合热力图(比例)', fontsize=14, fontweight='bold')# 添加数值标注for i in range(len(region_product_norm.index)):for j in range(len(region_product_norm.columns)):text = ax2.text(j, i, f'{region_product_norm.iloc[i, j]:.2f}',ha="center", va="center", color="white", fontweight='bold')# 添加颜色条cbar = plt.colorbar(im, ax=ax2, shrink=0.8)cbar.set_label('产品占比', rotation=270, labelpad=15)# 3. 地区月度销售趋势ax3 = axes[1, 0]region_monthly = self.sales_data.groupby(['Month', 'Region'])['Sales'].sum().unstack()colors_region = [self.colors['primary'], self.colors['secondary'], self.colors['success'], self.colors['warning'], self.colors['info']]for i, region in enumerate(region_monthly.columns):ax3.plot(region_monthly.index, region_monthly[region], marker='o', linewidth=2, label=region, color=colors_region[i])ax3.set_title('各地区月度销售趋势', fontsize=14, fontweight='bold')ax3.set_xlabel('月份')ax3.set_ylabel('销售额(元)')ax3.legend()ax3.grid(True, alpha=0.3)# 4. 地区销售表现雷达图ax4 = axes[1, 1]# 计算各地区的多个指标region_metrics = self.sales_data.groupby('Region').agg({'Sales': ['sum', 'mean', 'count'],'Quantity': 'sum'})# 扁平化列名region_metrics.columns = ['总销售额', '平均订单额', '订单数', '总数量']# 标准化指标(0-1范围)region_metrics_norm = region_metrics.div(region_metrics.max())# 选择一个地区进行雷达图展示selected_region = region_metrics_norm.index[0]values = region_metrics_norm.loc[selected_region].values# 设置雷达图categories = region_metrics_norm.columnsN = len(categories)# 计算角度angles = [n / float(N) * 2 * np.pi for n in range(N)]angles += angles[:1]  # 闭合图形# 闭合数据values = np.concatenate([values, [values[0]]])# 转换为极坐标ax4 = plt.subplot(2, 2, 4, projection='polar')ax4.plot(angles, values, 'o-', linewidth=2, color=self.colors['primary'])ax4.fill(angles, values, alpha=0.25, color=self.colors['primary'])# 设置标签ax4.set_xticks(angles[:-1])ax4.set_xticklabels(categories)ax4.set_ylim(0, 1)ax4.set_title(f'{selected_region}销售表现雷达图', fontsize=14, fontweight='bold', pad=20)plt.tight_layout()plt.show()print("✅ 地区分析图表创建完成")def create_comprehensive_dashboard(self):"""创建综合仪表板"""print("📊 创建综合销售仪表板...")# 创建大型仪表板fig = plt.figure(figsize=(24, 16))gs = fig.add_gridspec(4, 6, hspace=0.3, wspace=0.3)# 计算关键指标total_sales = self.sales_data['Sales'].sum()total_quantity = self.sales_data['Quantity'].sum()avg_order_value = self.sales_data['Sales'].mean()num_orders = len(self.sales_data)# 1. 关键指标卡片(顶部)metrics = [('总销售额', f'{total_sales/10000:.0f}万元', self.colors['primary']),('总销量', f'{total_quantity:,}件', self.colors['success']),('平均订单', f'{avg_order_value:.0f}元', self.colors['warning']),('订单数量', f'{num_orders:,}笔', self.colors['info'])]for i, (title, value, color) in enumerate(metrics):ax = fig.add_subplot(gs[0, i:i+1])ax.text(0.5, 0.7, value, ha='center', va='center', fontsize=24, fontweight='bold', color=color)ax.text(0.5, 0.3, title, ha='center', va='center', fontsize=14, color='gray')ax.set_xlim(0, 1)ax.set_ylim(0, 1)ax.axis('off')# 添加背景框ax.add_patch(plt.Rectangle((0.05, 0.1), 0.9, 0.8, facecolor=color, alpha=0.1, linewidth=2))# 2. 主要销售趋势图(左上大图)ax_main = fig.add_subplot(gs[1:3, 0:3])daily_sales = self.sales_data.groupby('Date')['Sales'].sum()ax_main.plot(daily_sales.index, daily_sales.values, color=self.colors['primary'], linewidth=1.5, alpha=0.7)# 添加移动平均线ma7 = daily_sales.rolling(window=7).mean()ma30 = daily_sales.rolling(window=30).mean()ax_main.plot(daily_sales.index, ma7, color=self.colors['danger'], linewidth=2, label='7天移动平均')ax_main.plot(daily_sales.index, ma30, color=self.colors['success'], linewidth=2, label='30天移动平均')ax_main.set_title('日销售额趋势分析', fontsize=16, fontweight='bold')ax_main.set_xlabel('日期')ax_main.set_ylabel('销售额(元)')ax_main.legend()ax_main.grid(True, alpha=0.3)# 3. 产品销售分布(右上)ax_product = fig.add_subplot(gs[1, 3:5])product_sales = self.sales_data.groupby('Product')['Sales'].sum()bars = ax_product.bar(range(len(product_sales)), product_sales.values,color=[self.colors['primary'], self.colors['secondary'], self.colors['success'], self.colors['warning'], self.colors['info']])ax_product.set_title('产品销售额分布', fontsize=14, fontweight='bold')ax_product.set_xticks(range(len(product_sales)))ax_product.set_xticklabels(product_sales.index, rotation=45)ax_product.set_ylabel('销售额(元)')# 4. 地区销售饼图(右中)ax_region = fig.add_subplot(gs[2, 3:5])region_sales = self.sales_data.groupby('Region')['Sales'].sum()wedges, texts, autotexts = ax_region.pie(region_sales.values, labels=region_sales.index,autopct='%1.1f%%', startangle=90)ax_region.set_title('地区销售分布', fontsize=14, fontweight='bold')# 5. 月度销售对比(右上角)ax_monthly = fig.add_subplot(gs[1:3, 5])monthly_sales = self.sales_data.groupby('Month')['Sales'].sum()bars = ax_monthly.bar(monthly_sales.index, monthly_sales.values,color=self.colors['info'], alpha=0.8)ax_monthly.set_title('月度销售', fontsize=12, fontweight='bold')ax_monthly.set_xlabel('月份')ax_monthly.set_ylabel('销售额')# 6. 销售热力图(底部左)ax_heatmap = fig.add_subplot(gs[3, 0:2])# 创建周-月热力图self.sales_data['Week'] = self.sales_data['Date'].dt.isocalendar().weekweek_month_sales = self.sales_data.groupby(['Month', 'Week'])['Sales'].sum().unstack(fill_value=0)# 只选择前12周week_month_sales = week_month_sales.iloc[:, :12]im = ax_heatmap.imshow(week_month_sales.values, cmap='YlOrRd', aspect='auto')ax_heatmap.set_title('月度-周度销售热力图', fontsize=12, fontweight='bold')ax_heatmap.set_xlabel('周')ax_heatmap.set_ylabel('月份')ax_heatmap.set_yticks(range(len(week_month_sales.index)))ax_heatmap.set_yticklabels(week_month_sales.index)# 7. 销售分布直方图(底部中)ax_dist = fig.add_subplot(gs[3, 2:4])ax_dist.hist(self.sales_data['Sales'], bins=30, alpha=0.7, color=self.colors['secondary'], edgecolor='black')ax_dist.set_title('单笔销售额分布', fontsize=12, fontweight='bold')ax_dist.set_xlabel('销售额(元)')ax_dist.set_ylabel('频次')ax_dist.axvline(self.sales_data['Sales'].mean(), color='red', linestyle='--', label=f'均值: {self.sales_data["Sales"].mean():.0f}')ax_dist.legend()# 8. 关键统计表格(底部右)ax_table = fig.add_subplot(gs[3, 4:6])ax_table.axis('tight')ax_table.axis('off')# 计算统计数据stats_data = [['统计指标', '数值'],['最高日销售', f'{daily_sales.max()/10000:.1f}万元'],['最低日销售', f'{daily_sales.min()/10000:.1f}万元'],['销售标准差', f'{daily_sales.std()/10000:.1f}万元'],['最佳产品', product_sales.idxmax()],['最佳地区', region_sales.idxmax()],['数据天数', f'{len(daily_sales)}天']]table = ax_table.table(cellText=stats_data, cellLoc='center', loc='center',colWidths=[0.5, 0.5])table.auto_set_font_size(False)table.set_fontsize(10)table.scale(1, 1.5)# 设置表格样式for i in range(len(stats_data)):if i == 0:for j in range(2):table[(i, j)].set_facecolor(self.colors['primary'])table[(i, j)].set_text_props(weight='bold', color='white')else:for j in range(2):table[(i, j)].set_facecolor('#f8f9fa' if i % 2 == 0 else '#ffffff')ax_table.set_title('关键统计指标', fontsize=12, fontweight='bold')# 添加总标题和时间戳fig.suptitle('销售数据综合分析仪表板', fontsize=24, fontweight='bold', y=0.98)# 添加生成时间current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')fig.text(0.99, 0.01, f'生成时间: {current_time}', ha='right', va='bottom', fontsize=10, color='gray')plt.show()print("✅ 综合仪表板创建完成")def export_charts(self, format='png', dpi=300):"""导出图表"""print(f"💾 导出图表为 {format} 格式...")# 重新创建所有图表并保存charts_info = [('时间序列分析', self.create_time_series_charts),('产品分析', self.create_product_analysis_charts),('地区分析', self.create_regional_analysis_charts),('综合仪表板', self.create_comprehensive_dashboard)]for chart_name, chart_func in charts_info:plt.figure()chart_func()filename = f'sales_{chart_name}.{format}'plt.savefig(filename, dpi=dpi, bbox_inches='tight', facecolor='white', edgecolor='none')plt.close()print(f"  ✅ {filename} 已保存")print("📁 所有图表已导出完成")def demo_sales_visualization():"""销售可视化完整演示"""print("🚀 销售趋势图表制作项目演示")print("=" * 50)# 创建可视化管理器viz_manager = SalesVisualizationManager()# 生成示例数据viz_manager.generate_sales_data(days=365)# 数据概览print(f"\n📋 数据概览:")print(f"数据形状: {viz_manager.sales_data.shape}")print(f"日期范围: {viz_manager.sales_data['Date'].min()}{viz_manager.sales_data['Date'].max()}")print(f"产品种类: {viz_manager.sales_data['Product'].nunique()}种")print(f"销售地区: {viz_manager.sales_data['Region'].nunique()}个")# 创建各类分析图表viz_manager.create_time_series_charts()viz_manager.create_product_analysis_charts()viz_manager.create_regional_analysis_charts()viz_manager.create_comprehensive_dashboard()print(f"\n🎉 销售趋势图表制作项目演示完成!")print("📊 你已经学会了创建专业的数据可视化图表")if __name__ == "__main__":demo_sales_visualization()

可视化最佳实践

图表选择指南

# 可视化最佳实践指南
print("📚 可视化最佳实践")
print("=" * 30)def choose_chart_type(data_type, purpose):"""根据数据类型和目的选择合适的图表类型参数:data_type: 数据类型purpose: 分析目的"""chart_guide = {('时间序列', '趋势分析'): '线图',('分类数据', '比较大小'): '柱状图',('分类数据', '部分整体'): '饼图',('两个连续变量', '相关关系'): '散点图',('单个连续变量', '分布形状'): '直方图',('多个数值变量', '综合比较'): '雷达图',('二维数据', '模式识别'): '热力图',('分类统计', '分布比较'): '箱线图'}return chart_guide.get((data_type, purpose), '根据具体情况选择')# 图表选择示例
scenarios = [('时间序列', '趋势分析', '股价变化、销售趋势'),('分类数据', '比较大小', '各产品销量对比'),('分类数据', '部分整体', '市场份额分析'),('两个连续变量', '相关关系', '身高体重关系'),('单个连续变量', '分布形状', '考试成绩分布'),('多个数值变量', '综合比较', '员工能力评估'),('二维数据', '模式识别', '地区产品销售'),('分类统计', '分布比较', '不同组别的数据分布')
]print("📊 图表类型选择指南:")
for data_type, purpose, example in scenarios:chart_type = choose_chart_type(data_type, purpose)print(f"  {data_type} + {purpose}{chart_type}")print(f"    示例: {example}")print()

设计原则

# 可视化设计原则
print("🎨 可视化设计原则")
print("=" * 25)principles = [{'principle': '简洁性原则','description': '去除不必要的装饰,突出数据本身','good_practice': ['使用简洁的配色', '避免3D效果', '减少图表垃圾'],'bad_practice': ['过多的颜色', '复杂的背景', '无关的装饰元素']},{'principle': '准确性原则', 'description': '确保图表准确反映数据','good_practice': ['从0开始的y轴', '合适的比例尺', '清晰的标签'],'bad_practice': ['截断的y轴', '误导的比例', '模糊的标签']},{'principle': '可读性原则','description': '确保观众能够轻松理解图表','good_practice': ['清晰的字体', '合适的大小', '有效的颜色对比'],'bad_practice': ['太小的字体', '低对比度', '难以区分的颜色']},{'principle': '一致性原则','description': '在同一报告中保持视觉风格统一','good_practice': ['统一的配色方案', '一致的字体', '相同的图例位置'],'bad_practice': ['混乱的颜色使用', '不同的字体样式', '随意的布局']}
]for principle in principles:print(f"🔵 {principle['principle']}")print(f"   {principle['description']}")print(f"   ✅ 好的做法: {', '.join(principle['good_practice'])}")print(f"   ❌ 避免: {', '.join(principle['bad_practice'])}")print()

学习总结

通过本节课的学习,你已经掌握了:

✅ Matplotlib基础概念

  • 理解了数据可视化在AI中的重要作用
  • 掌握了Figure、Axes、Axis的层次结构
  • 学会了pyplot和面向对象两种编程接口

✅ 基本图表类型

  • 熟练创建线图、柱状图、散点图、饼图、直方图
  • 掌握了各种图表的适用场景和最佳实践
  • 学会了图表的美化和自定义技巧

✅ 高级可视化技能

  • 掌握了复杂布局和子图管理
  • 学会了创建综合性的数据分析仪表板
  • 理解了颜色、样式、注释等美化要素

✅ 实际项目经验

  • 完成了完整的销售趋势分析项目
  • 体验了从数据到洞察的可视化流程
  • 学会了创建专业级的数据分析报告

✅ 最佳实践认知

  • 了解了图表类型的选择原则
  • 掌握了可视化设计的核心要素
  • 学会了避免常见的可视化陷阱

下节课预告

第7讲我们将学习OpenAI API使用,这是当前最热门的AI应用开发技能:

  • OpenAI API的基本概念和注册流程
  • GPT模型的API调用和参数设置
  • 提示词工程的技巧和最佳实践
  • 构建智能问答系统项目
  • 处理API限制和错误处理

掌握OpenAI API将让你能够构建各种智能应用!


🎉 恭喜完成第6讲!
你已经掌握了数据可视化这项重要技能。好的可视化能让数据说话,让复杂的分析结果变得直观易懂。现在你可以创建专业的图表和仪表板,为数据分析和AI项目增添强大的展示能力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86791.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM+JSP 的旅游管理系统

【旅游景点管理系统】【送文档】|SSM | JSP 【运行开发环境】 jdk1.8 idea mysql maven tomcat 【技术栈】 Spring SpringMVC mybatis JSP 【项目功能】 两个角色;管理员功能有游客管理、轮播图管理、景点管理、景点类型管理;普…

系统 | 电脑重置 图文教程

背景: 换内存条,换完,声卡网卡崩盘,分析原因可能是未断电操作(什么光感自动断电 还是手动的香),网卡由于代理没关,关完即可。声卡一直没好,电脑店说是硬件问题;自行排查了…

MyBatis深度面试指南

一、MyBatis核心解析:半ORM框架的底层真相 1. 本质与工作流 半ORM定义: 对象映射:通过ResultMap将ResultSet自动转为Java对象(省去JDBC手动映射)。SQL控制:开发者需手动编写SQL,框架不自动生成(与Hibernate核心区别)。工作流四步: 解析mybatis-config.xml → 构建Sq…

使用Docker部署mysql8

1、拉取mysql8的镜像: 1 [rooti-zgn6som8 ~]# docker pull mysql:8.0 2、创建配置和数据文件夹并修改权限: 1 2 3 4 mkdir -p /data/mysql8/conf mkdir -p /data/mysql8/data chmod -R 755 /data/mysql8/ 3、配置一个自定义的配置文件my.cnf: 1 …

Vue3—插槽solt

默认插槽 父组件 <Sidebar><div>{{ strData }}</div></Sidebar> let strData ref(我是你爸爸真伟大&#xff0c;养你这么大);//定义插槽数据子组件 <slot>没有数据&#xff0c;我先默认显示一下 loading。。。。。。。</slot>父组件提供…

时间同步 gptp ptp

目录 车载以太网PTP报文分析**PTP协议基础****PTP报文类型与功能****PTP报文格式解析****时钟同步原理与计算****车载以太网PTP分析工具****典型分析场景****车载场景特殊考虑**gPTP与PTP的对比解析**1. 基本概念****2. 核心差异对比****3. 技术细节对比****报文结构****主时钟…

AWS WebRTC:通过shell实现多进程启动viewer

​ 前面总结了aws webrtc sdk-c项目中多进程启动master的shell脚本,具体参考:https://blog.csdn.net/zhang_jiamin/article/details/148616899 这次总结一下多进程启动viewer的shell脚本,以及过程中遇到的问题和解决方法。 实现说明: 1、获取 sid 和 uid(用于认证) 2、…

设计模式(策略,工厂,单例,享元,门面)+模板方法

文章目录 前提策略模式思想实现如何拓展 模板方法存在的问题思想实现如何拓展 工厂模式实现问题及解决(解耦)配置文件方式使用注解 单例模式实现方式1,懒汉式(线程不安全)2,懒汉式(线程安全)3,饿汉式4,双重校验锁机制(面)5,静态内部类6,枚举 体现 享元模式门面模式 前提 假设做…

libarchive压缩解压文件

存在中文乱码问题 官网&#xff1a; libarchive - 用于读取和写入 tar、cpio、zip、ISO 和其他存档格式的 C 库和命令行工具 GitHub GitHub源码&#xff1a;Bluewind/libarchive: Multi-format archive and compression library (github.com) 参考&#xff1a; C archive_w…

AutoGPT,自主完成复杂任务

AutoGPT是一个开源的AI Agent项目&#xff0c;它的核心目标是让AI能够自主完成复杂任务&#xff0c;而不仅仅是回答单个问题。简单来说&#xff0c;它让AI具备了"自主思考和行动"的能力。 1. AutoGPT的核心概念 什么是AI Agent&#xff1f; AI Agent&#xff08;智…

lambda、function基础/响应式编程基础

lambda表达式 只要是函数式接口&#xff08;接口内只有一个未实现的方法&#xff0c;可以有其它默认方法&#xff09;&#xff0c;就可以用lambda表达式&#xff0c;也就是快速new一个匿名内部类。 实例化接口的三种方式 继承接口&#xff0c;并实现接口 直接实现匿名内部类 …

OpenTiny 体验官实操活动 | 快速体验 TinyVue 组件库的智能化交互能力

实验简介 通过体验基于标准 MCP 协议的 Web 智能组件库——TinyVue&#xff0c;开发者可以了解 AI 智能体控制 TinyVue 智能组件的各类行为。本次实验主要是在 TinyVue 官网上&#xff0c;开发者能够通过 AI 对话框&#xff0c;以语音或文字方式与网站组件进行互动&#xff0c…

秋招Day15 - Redis - 基础

什么是Redis&#xff1f; Redis是一种基于键值对的NoSQL数据库。 主要的特点是把数据放在内存中&#xff0c;读写速度相比于磁盘会快很多。 对于性能要求很高的场景&#xff0c;比如缓存热点数据&#xff0c;防止接口爆刷&#xff0c;都会用到Redis Redis还支持持久化&…

权限提升-工作流

一、Windows 权限提升 操作阶段 对应工具 说明 系统补丁与漏洞查询 systeminfo、WindowsVulnScan、wesng 提取 KB 补丁号&#xff0c;匹配 CVE 漏洞&#xff08;如 CVE-2020-1054&#xff09; 内核漏洞提权 MSF&#xff08;local_exploit_suggester&#xff09;、CVE 对…

c++手撕线程池

C手撕线程池 #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h>#define LL_ADD(item, list) do{ \item->prev NULL; \item->next list; \if…

cocos creator 3.8 - 精品源码 - 六边形消消乐(六边形叠叠乐、六边形堆叠战士)

cocos creator 3.8 - 精品源码 - 六边形消消乐 游戏介绍功能介绍免费体验下载开发环境游戏截图免费体验 游戏介绍 六边形堆叠战士(六边形消消消)是一款脱胎于2048、1010&#xff0c;基于俄罗斯方块的魔性方块达人小游戏&#xff0c;可以多方向多造型消除哦&#xff01; 功能介…

3ds Max高效运行配置核心要素

要保障3ds Max流畅运行&#xff0c;需围绕计算性能、图形处理、数据吞吐三大维度构建硬件体系。不同工作环节对硬件需求存在显著差异&#xff1a; 一、核心组件配置原则 CPU&#xff1a;线程与频率双优化 建模/视口操作&#xff1a;依赖高主频&#xff08;建议≥4.0GHz&#…

实变与泛函题解-心得笔记【16】

文章目录 集合参考文献 集合 参考文献 《实变函数论与泛函分析》

道路交通标志检测数据集-智能地图与导航 交通监控与执法 智慧城市交通管理-2,000 张图像

道路交通标志检测数据集 &#x1f4e6; 已发布目标检测数据集合集&#xff08;持续更新&#xff09;&#x1f6a7; 道路交通标志检测数据集介绍&#x1f4cc; 数据集概览包含类别 &#x1f3af; 应用场景&#x1f5bc; 数据样本展示 YOLOv8 训练实战&#x1f4e6; 1. 环境配置 …

一、jenkins介绍和gitlab部署

一、jenkins介绍 jenkins和持续集成的关系 Jenkins 是实现持续集成&#xff08;CI&#xff09;最流行的自动化工具&#xff0c;它负责自动构建、测试和部署代码&#xff0c;确保团队能频繁且可靠地集成代码变更。 持续集成和敏捷开发的关系 敏捷开发是一种"快速迭代、…