当前位置: 首页 > news >正文

【数据分析】03 - Matplotlib

【数据分析】03 - Matplotlib

文章目录

  • 【数据分析】03 - Matplotlib
    • 一:基础入门
      • 1:Matplotlib简介
        • 1.1:什么是Matplotlib
        • 1.2:Matplotlib架构
      • 2:基本的绘图流程
      • 3:图形基本元素
        • 3.1:图形容器Figure
        • 3.2:坐标轴系统 - axes
        • 3.3:坐标轴 - axis
        • 3.4:其他常用的基本元素
    • 二:核心绘图功能
      • 1:基本图表类型
        • 1.1:折线图plot
        • 1.2:散点图scatter
        • 1.3:柱状图bar/barh
        • 1.4:直方图hist
        • 1.5:饼图pie
        • 1.6:箱线图boxplot
      • 2:多子图绘制
        • 2.1:GridSpec 高级布局
        • 2.2:嵌套子图
      • 3:图形样式设置
        • 3.1:颜色设置
        • 3.2:线型设置
        • 3.3:标记设置
        • 3.4:透明度设置
        • 3.5:图形尺寸设置
    • 三:高级绘图功能
      • 1:高级图标类型
        • 1.1:面积图stackplot
        • 1.2:等高线图contour/contourf
        • 1.3:3D 绘图mplot3d
        • 1.4:极坐标图polar
        • 1.5:热力图imshow/pcolor
      • 2:动画和交互
        • 2.1:基本动画
        • 2.2:交互式绘图
        • 2.3:事件处理

一:基础入门

1:Matplotlib简介

1.1:什么是Matplotlib

Matplotlib 是 Python 中最著名的 2D 绘图库,它提供了一个面向对象的 API 和一系列函数,用于将数据可视化。

最初由 John D. Hunter 于 2003 年创建,现已成为 Python 科学计算生态系统中最核心的可视化工具之一。

主要特点:

  1. 跨平台性:可在 Windows、Linux 和 macOS 上运行
  2. 多种输出格式:支持 PNG、PDF、SVG、EPS 等多种格式
  3. 高度可定制:几乎可以控制图形的每个元素
  4. 丰富的图表类型:支持线图、散点图、条形图、直方图、饼图等
  5. 与科学计算库集成:与 NumPy、Pandas、SciPy 等无缝协作
  6. 交互式功能:支持缩放、平移和更新图形
1.2:Matplotlib架构

Matplotlib 采用三层架构设计,各层职责分明:

Backend 层(后端层) -> 处理与具体显示/输出设备的交互 -> 将 Artist 层生成的图形渲染到屏幕或文件中

主要后端类型如下:

  • Agg:用于生成 PNG 等静态图像文件(无显示功能)
  • TkAgg:基于 Tkinter 的交互式后端
  • QtAgg:基于 Qt 的交互式后端
  • GTK:基于 GTK 的交互式后端
  • WX:基于 WXWidgets 的交互式后端
  • MacOSX:macOS 原生后端
  • WebAgg:基于 Web 的后端(可在浏览器中显示)

Artist 层(艺术家层)-> 处理所有高级绘图元素(如线条、文本、图像等)

面向对象接口,提供对图形元素的精细控制

  • FigureCanvas:表示绘图区域
  • Renderer:知道如何在绘图区域上绘图
  • Artist:所有可见元素的基类
    • Figure:顶级容器,包含所有绘图元素
    • Axes:实际的绘图区域,包含坐标轴、标签等
    • Axis:坐标轴,处理刻度、标签等
    • Line2DTextPatch 等具体图形元素

Scripting 层(脚本层)-> 提供类似 MATLAB 的简单接口,便于快速绘图

  • 状态机接口,保持当前图形和坐标轴的状态
  • 适合交互式使用和简单脚本
  • 底层仍然使用 Artist 层

主要模块:

  • pyplot 模块:提供类似 MATLAB 的绘图命令
  • pylab 模块(不推荐使用):将 pyplot 和 numpy 合并到同一命名空间

2:基本的绘图流程

  1. 创建图形 (plt.figure())
  2. 创建子图 (plt.subplot()/add_subplot())
  3. 绘制简单图形 (plt.plot())
  4. 显示图形 (plt.show())

3:图形基本元素

3.1:图形容器Figure

顶级容器,相当于画布

创建一个新的图形窗口或画布

参数说明
figsize(宽度, 高度) 英寸为单位
dpi每英寸点数(分辨率)
facecolor背景颜色
edgecolor边框颜色
fig = plt.figure(figsize=(8, 6), dpi=100, facecolor='lightgray')
  • 可以包含一个或多个 Axes(子图)

  • 控制图形大小、DPI、背景色等全局属性

  • 常用方法:

    fig = plt.figure(figsize=(8,6), dpi=100, facecolor='white')
    fig.suptitle('Figure Title')  # 图形总标题
    
3.2:坐标轴系统 - axes

实际的绘图区域(子图)

  • 每个 Axes 包含 x 轴和 y 轴

  • 真正的绘图函数(如 plot())都是在 Axes 上调用的

  • 创建方法:

    ax = fig.add_subplot(111)  # 1行1列第1个子图
    # 或
    fig, ax = plt.subplots()  # 更现代的创建方式
    

创建子图 - plt.subplot() || fig.add_subplot || plt.subplots

方式一:plt.subplot(nrows, ncols, index)

plt.subplot(2, 2, 1)  # 创建2行2列的第1个子图, 就是创建nrows * ncols个子图,然后index是显示第几个

在这里插入图片描述

方式二:fig.add_subplot(nrows, ncols, index)

fig = plt.figure(figsize=(8, 6), dpi=100, facecolor='lightgray')
ax = fig.add_subplot(2, 2, 3)  # 在已创建的图形上添加子图

在这里插入图片描述

方式三:plt.subplots(nrows, nrols)

fig, ax = plt.subplots(nrows=2, ncols=2)  # 一次性创建多个子图

在这里插入图片描述

3.3:坐标轴 - axis

创建画布 -> 创建子图(坐标轴系统) -> 在子图中绘制坐标轴

实际的坐标轴对象:

  • 控制刻度、刻度标签、网格线等

  • 包含 XAxis 和 YAxis 两个对象

  • 常用定制方法:

    ax.xaxis.set_ticks([0, 1, 2])  # 设置x轴刻度
    ax.yaxis.set_tick_params(rotation=45)  # 旋转y轴标签
    
3.4:其他常用的基本元素

标题和标签

ax.set_title('Subplot Title')  # 子图标题
ax.set_xlabel('X Axis Label')  # x轴标签
ax.set_ylabel('Y Axis Label')  # y轴标签

图例 (Legend)

lines = ax.plot(x, y1, x, y2)
ax.legend(lines, ['Line 1', 'Line 2'], loc='upper right')

网格线 (Grid)

ax.grid(True, linestyle='--', alpha=0.5)  # 显示虚线网格

刻度 (Ticks)

ax.set_xticks([0, 1, 2, 3])  # 设置x轴刻度位置
ax.set_xticklabels(['A', 'B', 'C', 'D'])  # 设置刻度标签

注释 (Annotation)

ax.annotate('Important Point', xy=(2,1), xytext=(3,1.5),arrowprops=dict(facecolor='black'))

图形元素 (Shapes)

# 矩形
rect = plt.Rectangle((0.5,0.5), 0.2, 0.4, color='green')
ax.add_patch(rect)# 圆形
circle = plt.Circle((0.5,0.5), 0.1, color='red')
ax.add_patch(circle)

图形保存

plt.savefig('output.png', dpi=300, bbox_inches='tight')

二:核心绘图功能

1:基本图表类型

图表类型适用场景不适用场景
折线图趋势分析、时间序列非连续数据
散点图相关性分析、分布观察大数据集(需采样)
柱状图类别比较、离散数据连续数据分布
直方图数据分布、概率密度类别数据
饼图比例展示、组成分析多类别(>6)、精确比较
箱线图统计分布、异常值检测展示具体数据点
1.1:折线图plot

显示数据随时间或有序类别的变化趋势

plt.plot(x, y, fmt, **kwargs) 

plt.plot()是matplotlib中最基础且最常用的函数之一,用于绘制二维图形

x, y参数

必须参数,数据点的 x 坐标和 y 坐标

  • 可以是列表、元组或 numpy 数组
  • 如果只提供 y 值,x 值会自动生成为 [0, 1, 2, …, len(y)-1]

fmt

格式字符串由颜色、标记和线型三部分组成,格式为:[marker][line][color],顺序任意。

颜色 (color):

  • 'b': 蓝色
  • 'g': 绿色
  • 'r': 红色
  • 'c': 青色
  • 'm': 洋红
  • 'y': 黄色
  • 'k': 黑色
  • 'w': 白色

标记 (marker):

  • '.': 点
  • ',': 像素
  • 'o': 圆圈
  • 'v': 下三角
  • '^': 上三角
  • '<': 左三角
  • '>': 右三角
  • 's': 正方形
  • 'p': 五边形
  • '*': 星形
  • 'h': 六边形1
  • 'H': 六边形2
  • '+': 加号
  • 'x': x符号
  • 'D': 菱形
  • 'd': 小菱形
  • '|': 垂直线
  • '_': 水平线

线型 (linestyle):

  • '-': 实线
  • '--': 虚线
  • '-.': 点划线
  • ':': 点线
  • 'None'' ': 无线

常用关键字参数

  • colorc: 线条颜色 (可以接受十六进制颜色码如 '#FF0000')
  • linestylels: 线型
  • linewidthlw: 线宽 (浮点数)
  • marker: 标记样式
  • markersizems: 标记大小
  • markerfacecolormfc: 标记填充色
  • markeredgecolormec: 标记边缘色
  • markeredgewidthmew: 标记边缘宽度
  • label: 图例标签
  • alpha: 透明度 (0-1)
  • zorder: 绘图顺序 (数值大的显示在上层)
import matplotlib.pyplot as plt
import numpy as npx = np.linspace(0, 10, 100)
y = np.sin(x)plt.plot(x, y)  # 最简单的折线图
plt.show()plt.plot(x, y, 'ro--')  # 红色圆圈标记,虚线
plt.plot(x, y, 'g^:', linewidth=2, markersize=8)  # 绿色上三角标记,点线plt.plot(x, y, color='blue', linestyle='-', linewidth=2, marker='o', markersize=6, markerfacecolor='red', label='sin(x)')y2 = np.cos(x)
plt.plot(x, y, 'b-', label='sin(x)')
plt.plot(x, y2, 'r--', label='cos(x)')
plt.legend()# 设置数据点之间的插值方式
plt.plot(x, y, drawstyle='steps-post')  # 阶梯图# 使用不同的缩放
plt.plot(x, y, '-', x, y*2, '--')  # 同时绘制两条线line, = plt.plot(x, y, 'b-')
line.set_linestyle(':')  # 之后将线改为点线
line.set_color('r')      # 改为红色
1.2:散点图scatter

展示两个变量之间的关系,发现数据分布、聚类或异常值

plt.scatter(x, y, s=None, c=None, marker=None, **kwargs)
  • x, y: 数据点坐标
  • s: 点的大小(标量或与x,y同长度的数组)
  • c: 点颜色(颜色字符串或颜色序列)
  • marker: 点形状,如 'o', 's', '^'
import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 随机生成数据 - 50个点
x = np.random.rand(50)
y = np.random.rand(50)
# 随机生成颜色和尺寸
colors = np.random.rand(50)
sizes = 1000 * np.random.rand(50)# alpha参数控制透明度
plt.scatter(x, y, c=colors, s=sizes, alpha=0.5)
plt.colorbar()  # 显示颜色条
plt.title('散点图示例')
plt.show()
1.3:柱状图bar/barh
特征垂直柱状图水平柱状图直方图
坐标方向垂直水平垂直
适用场景类别比较长标签/排名数据分布
X轴类别标签数值数值区间
Y轴数值类别标签频数/频率

垂直柱状图最适合比较少量类别间的数值差异,当类别标签较长或类别较多时,建议改用水平柱状图

垂直柱状图 - bar

比较不同类别的离散数据

# x -> 柱子的x坐标(类别位置)-> 可以是标量序列(如列表、数组)或类别标签
# height -> 柱子的高度(数值)
# width -> 柱子宽度(默认0.8), 范围在0-1之间,大于1会导致柱子重叠
# bottom -> 柱子底部基准(用于堆叠柱状图)
# align -> 柱子对齐方式 -> 'center':以x坐标为中心(默认)-> 'edge':以x坐标为左边缘
# color/facecolor:柱子填充色 -> 可接受颜色名称、十六进制或RGB值
# edgecolor:边框颜色
# linewidth/lw:边框宽度
# alpha:透明度(0-1)
# label:图例标签
plt.bar(x, height, width=0.8, bottom=None, **kwargs)# ============== 示例 ======================
import matplotlib.pyplot as plt
import numpy as np# 定义横纵坐标的内容
categories = ['Apple', 'Banana', 'Orange', 'Grape']
values = [23, 45, 56, 12]# 柱子的颜色是skyblue, 边框颜色是black
plt.bar(categories, values, color='skyblue', edgecolor='black')
# 标题,x标签,y标签
plt.title('Fruit Sales')
plt.xlabel('Fruit Type')
plt.ylabel('Sales Quantity')
# grid样式
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()

在这里插入图片描述

如果是多组柱状图

import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsecategories = ['Apple', 'Banana', 'Orange', 'Grape']
values = [23, 45, 56, 12]n = len(categories)
width = 0.35  # 柱子宽度# 第一组数据
plt.bar(np.arange(n) - width/2, values, width, label='2022')
# 第二组数据
plt.bar(np.arange(n) + width/2, [x*1.2 for x in values], width, label='2023')plt.xticks(np.arange(n), categories)  # 设置x轴标签
plt.legend()
plt.show()

在这里插入图片描述

如果是堆叠柱状图

import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsecategories = ['Apple', 'Banana', 'Orange', 'Grape']
values = [23, 45, 56, 12]bottom_values = [20, 30, 40, 10]
top_values = [15, 20, 25, 8]plt.bar(categories, bottom_values, label='Base')
plt.bar(categories, top_values, bottom=bottom_values, label='Bonus')
plt.legend()
plt.show()

水平柱状图 (barh)

# y:柱子的y坐标(类别位置) -> 可以是标量序列或类别标签
# width:柱子的宽度(数值)
# height:柱子高度(默认0.8)-> 相当于垂直柱状图中的width参数
# left:柱子左边缘基准(用于堆叠柱状图)
# align:柱子对齐方式 -> 'center':以y坐标为中心(默认) -> 'edge':以y坐标为下边缘
# color/facecolor:柱子填充色 -> 可接受颜色名称、十六进制或RGB值
# edgecolor:边框颜色
# linewidth/lw:边框宽度
# alpha:透明度(0-1)
# label:图例标签
plt.barh(y, width, height=0.8, left=None, *, align='center', **kwargs)# ========== 举一个例子 =================
import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falseimport matplotlib.pyplot as plt# 定义y -> 类别
categories = ['金融服务', '医疗健康', '教育培训', '电子商务']
# 定义x -> 数值
values = [120, 85, 65, 110]plt.barh(categories, values, color='lightgreen', edgecolor='darkgreen')
plt.title('行业投资金额(百万美元)')
plt.xlabel('投资金额')
plt.ylabel('行业类别')
plt.grid(axis='x', linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()

在这里插入图片描述

同理,多组的水平柱状图如下

import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsecategories = ['金融服务', '医疗健康', '教育培训', '电子商务']
values = [120, 85, 65, 110]n = len(categories)
height = 0.35  # 柱子高度# 第一组数据(左侧)
plt.barh(np.arange(n) - height/2, values, height, label='2022')
# 第二组数据(右侧)
plt.barh(np.arange(n) + height/2, [x*1.3 for x in values], height, label='2023')plt.yticks(np.arange(n), categories)
plt.legend()
plt.tight_layout()
plt.show()
1.4:直方图hist

基础直方图

import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 生成随机数据 - 1000个数据
data = np.random.normal(0, 1, 1000)  # 均值为0,标准差为1的正态分布# 绘制基础直方图
# 创建一个figure对象,并设置大小为8 x 6
plt.figure(figsize=(8, 6))
# 创建直方图,bins表示直方图的柱数,color表示柱的颜色,edgecolor表示柱的边框颜色
plt.hist(data, bins=30, color='steelblue', edgecolor='white')# 添加标题和标签
plt.title('基础直方图示例', fontsize=14)
plt.xlabel('数值范围', fontsize=12)
plt.ylabel('频数', fontsize=12)# 添加网格线
plt.grid(axis='y', alpha=0.3)plt.show()

在这里插入图片描述

可以自定义一些直方图的参数

import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 生成随机数据 - 1000个数据
data = np.random.normal(0, 1, 1000)  # 均值为0,标准差为1的正态分布plt.figure(figsize=(8, 6))# 更多自定义参数
plt.hist(data,bins=50,                   # 柱子数量range=(-3, 3),             # 数值范围density=True,              # 显示密度而非频数color='#FF6B6B',           # 柱子颜色edgecolor='#4D96FF',       # 边缘颜色linewidth=1.2,             # 边缘线宽alpha=0.7,                 # 透明度histtype='stepfilled',     # 直方图类型label='正态分布')          # 图例标签plt.title('自定义参数直方图', fontsize=14)
plt.xlabel('数值', fontsize=12)
plt.ylabel('概率密度', fontsize=12)
plt.legend(fontsize=10)
plt.grid(axis='y', linestyle='--', alpha=0.5)plt.show()

可以多组直方图进行比较

import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 生成多组数据
data1 = np.random.normal(0, 1, 1000)
data2 = np.random.normal(2, 1.5, 800)
data3 = np.random.normal(-2, 0.8, 1200)plt.figure(figsize=(10, 6))# 绘制多组直方图
plt.hist(data1, bins=30, alpha=0.5, label='组1: μ=0, σ=1')
plt.hist(data2, bins=30, alpha=0.5, label='组2: μ=2, σ=1.5')
plt.hist(data3, bins=30, alpha=0.5, label='组3: μ=-2, σ=0.8')plt.title('多组数据直方图比较', fontsize=14)
plt.xlabel('数值', fontsize=12)
plt.ylabel('频数', fontsize=12)
plt.legend(fontsize=10)
plt.grid(axis='y', alpha=0.3)plt.show()

还可以直方图配合密度曲线

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import seaborn as snsplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falseplt.figure(figsize=(10, 6))data = np.random.normal(loc=0, scale=1, size=1000)# 绘制直方图
plt.hist(data, bins=30, density=True,color='lightgreen',edgecolor='black',alpha=0.7,label='直方图')# 添加核密度估计曲线
sns.kdeplot(data, color='red', linewidth=2, label='密度曲线')# 添加理论正态分布曲线
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, np.mean(data), np.std(data))
plt.plot(x, p, 'k--', linewidth=1.5, label='理论正态分布')plt.title('直方图与密度曲线', fontsize=14)
plt.xlabel('数值', fontsize=12)
plt.ylabel('密度', fontsize=12)
plt.legend(fontsize=10)plt.show()

在这里插入图片描述

1.5:饼图pie

基础饼图

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import seaborn as snsplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 数据准备
labels = ['A', 'B', 'C', 'D']
sizes = [15, 30, 45, 10]  # 各部分大小
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']  # 颜色# 绘制饼图
plt.figure(figsize=(8, 6))
plt.pie(sizes,labels=labels,colors=colors,autopct='%1.1f%%',  # 显示百分比格式startangle=90)  # 起始角度# 添加标题
plt.title('基础饼图示例', fontsize=14)# 显示为圆形(防止压缩变形)
plt.axis('equal')
plt.show()

在这里插入图片描述

可以通过属性,添加突出和阴影效果

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import seaborn as snsplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 数据准备
labels = ['A', 'B', 'C', 'D']
sizes = [15, 30, 45, 10]  # 各部分大小
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']  # 颜色# 突出显示某一块(这里突出第2块)
explode = (0, 0.1, 0, 0)plt.figure(figsize=(8, 6))
plt.pie(sizes,explode=explode,  # 突出显示labels=labels,colors=colors,autopct='%1.1f%%',shadow=True, # 阴影效果startangle=90)plt.title('带阴影和突出显示的饼图', fontsize=14)
plt.axis('equal')
plt.show()

在这里插入图片描述

如果是环形图,其实就是在饼图的基础上上面在画一个圆

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import seaborn as snsplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 数据准备
labels = ['A', 'B', 'C', 'D']
sizes = [15, 30, 45, 10]  # 各部分大小
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']  # 颜色# 突出显示某一块(这里突出第2块)
explode = (0, 0.1, 0, 0)plt.figure(figsize=(8, 6))# 先画饼图
pie = plt.pie(sizes,labels=labels,colors=colors,autopct='%1.1f%%',startangle=90)# 添加一个白色圆形在中心
centre_circle = plt.Circle((0, 0), 0.7, color='white')
fig = plt.gcf()
fig.gca().add_artist(centre_circle)plt.title('环形图(甜甜圈图)示例', fontsize=14)
plt.axis('equal')
plt.show()
1.6:箱线图boxplot

箱线图(又称盒须图)是展示数据分布特征的重要工具,可以直观显示数据的中位数、四分位数、异常值等统计信息

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import seaborn as snsplt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 生成随机数据
np.random.seed(42)
data = np.random.normal(loc=0, scale=1, size=100)# 绘制基础箱线图
plt.figure(figsize=(8, 6))
plt.boxplot(data, patch_artist=True)  # patch_artist=True允许填充颜色# 添加标题和标签
plt.title('基础箱线图', fontsize=14)
plt.ylabel('数值', fontsize=12)
plt.xticks([1], ['数据集'])  # 设置x轴标签plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()

在这里插入图片描述

当然还可以自定义样式

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import seaborn as sns# 设置中文字体,确保图表中的中文能够正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用黑体
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False# 创建一个新的图像,指定大小
plt.figure(figsize=(10, 6))# 生成三组正态分布的随机数据,用于绘制箱线图
np.random.seed(42)
data1 = np.random.normal(0, 1, 100)
data2 = np.random.normal(2, 1.5, 100)
data3 = np.random.normal(-1, 0.8, 100)
all_data = [data1, data2, data3]# 定义箱线图中箱子的颜色
colors = ['#FF9F43', '#48CFAD', '#4FC1E9']# 绘制自定义样式的箱线图
box = plt.boxplot(all_data,patch_artist=True,  # 允许自定义填充颜色labels=['组1', '组2', '组3'],  # 设置每个数据组的标签widths=0.6,          # 箱体宽度showmeans=True,      # 显示均值meanline=True,       # 均值显示为线showfliers=True,     # 显示异常值flierprops=dict(      # 异常点样式marker='o',markerfacecolor='red',markersize=8,markeredgecolor='none'),medianprops=dict(     # 中位数线样式color='white',linewidth=2),meanprops=dict(       # 均值线样式color='yellow',linewidth=2),whiskerprops=dict(    # 须线样式color='gray',linewidth=1.5),capprops=dict(       # 箱体顶端线样式color='gray',linewidth=1.5))# 为每个箱子设置颜色和透明度
for patch, color in zip(box['boxes'], colors):patch.set_facecolor(color)patch.set_alpha(0.8)  # 设置透明度# 添加图表标题和y轴标签
plt.title('自定义样式的箱线图', fontsize=14)
plt.ylabel('数值分布', fontsize=12)# 添加网格,便于观察数据分布
plt.grid(axis='y', linestyle='--', alpha=0.5)# 显示图表
plt.show()

2:多子图绘制

前面已经介绍过了 subplot 函数和 subplots 函数,下面看看还有那些绘制子图的知识点

2.1:GridSpec 高级布局

GridSpec是Matplotlib中用于创建复杂子图布局的强大工具,它比简单的subplot()subplots()函数提供了更精细的控制。

GridSpec不是直接创建子图的函数,而是一个指定网格布局的类,然后你可以在这个网格的特定位置创建子图。

  1. 创建GridSpec对象,指定网格的行数和列数
  2. 使用subplot()函数并传入GridSpec的切片来创建子图
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpecfig = plt.figure(figsize=(10, 6))# 创建2行3列的网格
gs = GridSpec(2, 3, figure=fig)# 在网格的不同位置创建子图
ax1 = fig.add_subplot(gs[0, 0])  # 第一行第一列
ax2 = fig.add_subplot(gs[0, 1:])  # 第一行第二和第三列
ax3 = fig.add_subplot(gs[1, :2])  # 第二行第一和第二列
ax4 = fig.add_subplot(gs[1, 2])  # 第二行第三列# 添加一些示例内容
ax1.plot([1, 2, 3], [1, 2, 3])
ax2.bar(['A', 'B', 'C'], [3, 7, 2])
ax3.scatter([1, 2, 3], [3, 2, 1])
ax4.pie([15, 30, 45, 10], labels=['A', 'B', 'C', 'D'])plt.tight_layout()
plt.show()

在这里插入图片描述

高级设置 - 调整子图间距

gs = GridSpec(2, 2, figure=fig, width_ratios=[1, 2],  # 列宽度比例height_ratios=[2, 1],  # 行高度比例wspace=0.4,  # 列间距hspace=0.3)  # 行间距

高级设置 - 跨越多行/列的子图

gs = GridSpec(3, 3, figure=fig)# 创建跨越多行/列的子图
ax1 = fig.add_subplot(gs[:2, :])  # 占据前两行所有列
ax2 = fig.add_subplot(gs[2, :2])  # 占据第三行前两列
ax3 = fig.add_subplot(gs[2, 2])   # 占据第三行第三列

再举一个复杂的例子

import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as npdef grid_spec_test():# 创建一个Figure对象, 并设置大小为10x8fig = plt.figure(figsize=(10, 8))# 创建一个GridSpec对象, 宽高比为1:1, 4 * 4gs = GridSpec(4, 4, figure=fig)# 主图占据前3行和前3列ax_main = fig.add_subplot(gs[:3, :3])# 右侧颜色条占据前3行第4列ax_color = fig.add_subplot(gs[:3, 3])# 底部直方图占据第4行前3列ax_hist = fig.add_subplot(gs[3, :3])# 生成一些数据x = np.random.randn(1000)y = np.random.randn(1000)# 在主图中绘制散点图sc = ax_main.scatter(x, y, c=np.sqrt(x ** 2 + y ** 2), alpha=0.6)# 添加颜色条plt.colorbar(sc, cax=ax_color)# 在底部绘制直方图ax_hist.hist(x, bins=30, alpha=0.7)plt.tight_layout()plt.show()if __name__ == '__main__':grid_spec_test()

在这里插入图片描述

2.2:嵌套子图

嵌套子图是Matplotlib中创建复杂布局的高级技术,它允许你在一个主图中嵌入多个子图,或者在一个子图中再创建子图

基本创建方式

# 使用`add_axes()`手动定位
import matplotlib.pyplot as pltfig = plt.figure(figsize=(10, 8))# 主图
main_ax = fig.add_subplot(111)
main_ax.plot([1, 2, 3], [1, 2, 3], 'r-')# 在(0.2, 0.6)位置创建嵌套子图,宽度和高度为0.2
inset_ax = fig.add_axes([0.2, 0.6, 0.2, 0.2])  # [left, bottom, width, height]
inset_ax.plot([1, 2, 3], [3, 2, 1], 'b--')
inset_ax.set_title('嵌套子图')plt.show()# 使用inset_axes()方法
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axesfig, ax = plt.subplots(figsize=(8, 6))
ax.plot([1, 2, 3], [1, 2, 3])# 在主图中创建嵌套子图
inset_ax = inset_axes(ax, width="30%",  # 宽度为主图的30%height="20%",  # 高度为主图的20%loc='upper right')  # 位置在右上角inset_ax.plot([1, 2, 3], [3, 2, 1], 'g-')
inset_ax.set_title('使用inset_axes创建')

高级嵌套技术

# 多级嵌套子图
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12, 8))# 一级主图
main_ax = fig.add_subplot(111)
main_ax.plot([0, 1, 2], [0, 1, 0], 'k-')# 二级嵌套子图
inset1 = fig.add_axes([0.2, 0.6, 0.3, 0.3])
inset1.plot([1, 2, 3], [1, 3, 1], 'b-')# 三级嵌套子图(在二级子图中再嵌套)
inset2 = inset1.inset_axes([0.5, 0.5, 0.4, 0.4])
inset2.plot([1, 2], [2, 1], 'r--')
inset2.set_title('三级嵌套')plt.show()# 使用GridSpec实现嵌套布局
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpecfig = plt.figure(figsize=(10, 8))# 外层GridSpec:1行2列
outer_gs = GridSpec(1, 2, figure=fig, width_ratios=[3, 1])# 内层GridSpec:2行1列(用于左侧主区域)
inner_gs = GridSpec(2, 1, figure=fig, left=0.05, right=0.65,  # 定位hspace=0.3)  # 行间距# 创建子图
main_ax1 = fig.add_subplot(inner_gs[0])
main_ax2 = fig.add_subplot(inner_gs[1])
side_ax = fig.add_subplot(outer_gs[1])# 填充内容
main_ax1.plot([1, 2, 3], [1, 2, 1])
main_ax2.scatter([1, 2, 3], [3, 1, 2])
side_ax.bar(['A', 'B', 'C'], [2, 3, 1])plt.show()

实用嵌套模式

# 放大局部区域
import matplotlib.pyplot as plt
import numpy as npfig, ax = plt.subplots(figsize=(8, 6))x = np.linspace(0, 10, 1000)
y = np.sin(x) * np.exp(-x/10)
ax.plot(x, y)# 创建放大区域
inset_ax = inset_axes(ax, width="40%", height="30%", loc='upper right')
inset_ax.plot(x, y)
inset_ax.set_xlim(4, 6)  # 放大x=4到6的区域
inset_ax.set_ylim(0.2, 0.5)# 添加连接线
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
mark_inset(ax, inset_ax, loc1=2, loc2=4, fc="none", ec="0.5")plt.show()# 仪表板式嵌套布局
fig = plt.figure(figsize=(12, 10))# 定义布局:主图+3个小图
main_ax = fig.add_axes([0.1, 0.3, 0.6, 0.6])  # 主图
small1 = fig.add_axes([0.75, 0.7, 0.2, 0.2])  # 右上小图
small2 = fig.add_axes([0.75, 0.4, 0.2, 0.2])  # 右中小图
small3 = fig.add_axes([0.1, 0.1, 0.6, 0.15])  # 底部长图# 填充内容
x = np.linspace(0, 2*np.pi, 100)
main_ax.plot(x, np.sin(x), label='sin(x)')
main_ax.plot(x, np.cos(x), label='cos(x)')
main_ax.legend()small1.pie([15, 30, 45, 10], labels=['A', 'B', 'C', 'D'])
small2.barh(['X', 'Y', 'Z'], [3, 7, 2])
small3.hist(np.random.randn(1000), bins=30)plt.show()

嵌套子图的样式控制

# 边框和背景控制
fig, ax = plt.subplots()# 创建嵌套子图并设置样式
inset_ax = inset_axes(ax, width="30%", height="30%", loc='lower left',borderpad=2,  # 边框间距bbox_to_anchor=(0.4, 0.4),  # 锚点位置bbox_transform=ax.transAxes)  # 使用轴坐标inset_ax.plot([1, 2, 3], [3, 1, 2])
inset_ax.set_facecolor('lightgray')  # 背景色
inset_ax.spines['top'].set_linestyle('--')  # 上边框虚线
inset_ax.spines['right'].set_visible(False)  # 隐藏右边框plt.show()# 共享坐标轴
fig, axs = plt.subplots(2, 1, figsize=(8, 6))# 在第一个子图中创建嵌套子图
inset_ax = axs[0].inset_axes([0.6, 0.6, 0.3, 0.3])# 共享x轴
shared_inset = axs[1].inset_axes([0.1, 0.6, 0.3, 0.3], sharex=axs[1])# 填充内容
axs[0].plot([1, 2, 3], [1, 2, 1])
inset_ax.plot([1.5, 2.5], [1.5, 1.5], 'r-')axs[1].plot(np.arange(10), np.random.rand(10))
shared_inset.plot(np.arange(3, 7), np.random.rand(4), 'g--')plt.show()

3:图形样式设置

3.1:颜色设置

Matplotlib 提供了多种方式来指定颜色:

import matplotlib.pyplot as plt
import numpy as np# 1. 使用预定义的颜色名称
plt.plot([1, 2, 3], color='red')# 2. 使用十六进制颜色代码
plt.plot([1, 2, 3], color='#FF5733')# 3. RGB或RGBA元组 (值在0-1之间)
plt.plot([1, 2, 3], color=(0.1, 0.2, 0.5, 0.8))  # RGBA# 4. 使用灰度字符串 (0-1之间的字符串)
plt.plot([1, 2, 3], color='0.75')  # 75%灰度# 5. 使用CN颜色循环中的颜色
plt.plot([1, 2, 3], color='C1')  # 使用颜色循环中的第二个颜色

Matplotlib 支持所有标准的HTML/CSS颜色名称,如:

  • 基本颜色:'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black', 'white'
  • 灰色调:'gray', 'lightgray', 'darkgray'
  • 其他:'orange', 'purple', 'pink', 'brown'

同时还可以进行颜色映射:

x = np.linspace(0, 10, 100)
y = np.sin(x)
colors = np.linspace(0, 1, len(x))# 使用colormap
plt.scatter(x, y, c=colors, cmap='viridis')
plt.colorbar()  # 显示颜色条

常用colormap:

  • 顺序型:'viridis', 'plasma', 'inferno', 'magma', 'cividis'
  • 发散型:'coolwarm', 'bwr', 'seismic'
  • 循环型:'twilight', 'hsv'
3.2:线型设置

基本线型如下:

# 实线 (默认)
plt.plot([1, 2, 3], linestyle='-')  # 或 '-'# 虚线
plt.plot([1, 2, 3], linestyle='--')  # 或 '--'# 点划线
plt.plot([1, 2, 3], linestyle='-.')  # 或 '-.'# 点线
plt.plot([1, 2, 3], linestyle=':')  # 或 ':'# 无线条 (只显示标记)
plt.plot([1, 2, 3], linestyle='None')  # 或 'None' 或 ''

还可以自定义线型

# 使用元组定义线型 (线段长度, 空白长度, ...)
plt.plot([1, 2, 3], linestyle=(0, (1, 1)))  # 点线
plt.plot([1, 2, 3], linestyle=(0, (5, 5, 1, 5)))  # 自定义点划线
3.3:标记设置

基本标记设置:

# 圆形
plt.plot([1, 2, 3], marker='o')  # 或 'o'# 方形
plt.plot([1, 2, 3], marker='s')  # 或 's'# 三角形
plt.plot([1, 2, 3], marker='^')  # 向上三角形# 其他常见标记
# '+' 加号, 'x' 叉号, '*' 星号, 'D' 钻石形, 'd' 小钻石形, 'p' 五边形

标记大小颜色和样式填充

plt.plot([1, 2, 3], marker='o', markersize=10,  # 或 ms=10markerfacecolor='red',  # 标记填充色markeredgecolor='blue',  # 标记边缘色markeredgewidth=2)  # 标记边缘宽度plt.plot([1, 2, 3], marker='o', markerfacecolor='none',  # 无填充markeredgecolor='blue')
3.4:透明度设置
# global
plt.plot([1, 2, 3], alpha=0.5)  # 50%透明度# 不同元素的透明度
# 填充区域的透明度
plt.fill_between([1, 2, 3], [1, 2, 1], alpha=0.3)# 散点图的透明度
plt.scatter(np.random.rand(50), np.random.rand(50), alpha=0.6)# 条形图的透明度
plt.bar([1, 2, 3], [3, 2, 1], alpha=0.7)

还可以设置图片的透明度

img = np.random.rand(10, 10)
plt.imshow(img, alpha=0.8)
3.5:图形尺寸设置

创建图形时设置尺寸

# 设置图形尺寸 (宽度, 高度) 单位英寸
plt.figure(figsize=(8, 6))  # 8英寸宽,6英寸高

DPI设置

# 设置DPI (每英寸点数)
plt.figure(figsize=(8, 6), dpi=100)

调整现有图形尺寸

fig = plt.gcf()
fig.set_size_inches(10, 5)  # 调整现有图形尺寸

保存图形时的尺寸和DPI

plt.savefig('output.png', dpi=300, bbox_inches='tight')

子图间距调整

plt.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9,wspace=0.4, hspace=0.4)

约束布局

# 自动调整布局
plt.figure(constrained_layout=True)

三:高级绘图功能

1:高级图标类型

1.1:面积图stackplot

面积图(stackplot)是一种用于展示多个数据序列累积效果的可视化图表,特别适合显示各部分随时间变化的累积关系。Matplotlib 中的 stackplot() 函数可以方便地创建这种图表。

基本用法

最简单的堆叠面积图

import matplotlib.pyplot as plt
import numpy as np# 创建数据
x = np.arange(1, 6)  # x轴数据
y1 = np.array([1, 2, 3, 4, 5])  # 第一组数据
y2 = np.array([2, 3, 4, 5, 6])  # 第二组数据
y3 = np.array([3, 4, 5, 6, 7])  # 第三组数据# 绘制堆叠面积图
plt.stackplot(x, y1, y2, y3)
plt.title('基本堆叠面积图')
plt.show()

参数详解

主要参数

  • x:x轴数据(1D数组)
  • y:y轴数据(多个1D数组或2D数组)
  • labels:各系列的标签(用于图例)
  • colors:各系列的颜色
  • baseline:基线计算方法(‘zero’(默认), ‘sym’, ‘wiggle’, ‘weighted_wiggle’)

完整参数示例

plt.stackplot(x, y1, y2, y3,labels=['系列A', '系列B', '系列C'],colors=['#FF5733', '#33FF57', '#3357FF'],alpha=0.8,  # 透明度baseline='zero')  # 基线方法
plt.legend(loc='upper left')
plt.title('带标签和自定义颜色的堆叠面积图')
plt.show()

高级用法

使用DataFrame数据

import pandas as pd# 创建DataFrame
data = {'年份': [2018, 2019, 2020, 2021, 2022],'产品A': [200, 220, 250, 270, 300],'产品B': [150, 160, 170, 190, 210],'产品C': [100, 120, 140, 160, 180]
}
df = pd.DataFrame(data)# 绘制堆叠面积图
plt.stackplot(df['年份'], df['产品A'], df['产品B'], df['产品C'],labels=['产品A', '产品B', '产品C'],colors=['#FF9999', '#66B2FF', '#99FF99'])
plt.legend(loc='upper left')
plt.title('使用DataFrame绘制的堆叠面积图')
plt.xlabel('年份')
plt.ylabel('销售额')
plt.show()

自定义基线方法

# 创建数据
x = np.linspace(0, 2*np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)# 四种不同的基线方法
baselines = ['zero', 'sym', 'wiggle', 'weighted_wiggle']fig, axs = plt.subplots(2, 2, figsize=(12, 8))
axs = axs.flatten()for ax, baseline in zip(axs, baselines):ax.stackplot(x, y1, y2, baseline=baseline)ax.set_title(f"基线方法: '{baseline}'")ax.set_xlim(0, 2*np.pi)plt.tight_layout()
plt.show()

边缘线样式设置

# 创建数据
days = np.arange(1, 8)
sleep = [7, 6, 8, 7, 9, 8, 10]
work = [8, 9, 7, 8, 6, 9, 5]
leisure = [9, 9, 9, 9, 9, 7, 9]# 绘制堆叠面积图并设置边缘线
plt.stackplot(days, sleep, work, leisure,labels=['睡眠', '工作', '休闲'],colors=['#8ECFC9', '#FFBE7A', '#FA7F6F'],edgecolor='black',  # 边缘颜色linewidth=0.5)     # 边缘线宽plt.legend(loc='upper left')
plt.title('每日活动时间分配')
plt.xlabel('星期')
plt.ylabel('小时')
plt.xticks(days, ['周一', '周二', '周三', '周四', '周五', '周六', '周日'])
plt.show()

部分堆叠面积图

# 创建数据
months = np.arange(1, 13)
sales_A = np.random.randint(20, 50, size=12)
sales_B = np.random.randint(10, 30, size=12)
sales_C = np.random.randint(5, 20, size=12)# 只堆叠B和C,A单独显示
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))# 上方:全部堆叠
ax1.stackplot(months, sales_A, sales_B, sales_C,labels=['产品A', '产品B', '产品C'])
ax1.set_title('完全堆叠面积图')
ax1.legend(loc='upper left')# 下方:部分堆叠
ax2.plot(months, sales_A, label='产品A', color='#FF5733')
ax2.stackplot(months, sales_B, sales_C,labels=['产品B', '产品C'],colors=['#33FF57', '#3357FF'])
ax2.set_title('部分堆叠面积图')
ax2.legend(loc='upper left')plt.tight_layout()
plt.show()

实用技巧

添加数值标签

# 创建数据
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
revenue = [40, 60, 80, 70]
cost = [20, 30, 40, 35]
profit = [20, 30, 40, 35]# 计算累积高度用于标签位置
cum_height = np.vstack((np.zeros(len(quarters)), np.array(revenue), np.array(revenue)+np.array(cost))).T# 绘制堆叠面积图
plt.stackplot(quarters, revenue, cost, profit,labels=['收入', '成本', '利润'],colors=['#4CAF50', '#F44336', '#2196F3'])# 添加数值标签
for i, q in enumerate(quarters):plt.text(i, cum_height[i][1]/2, f'{revenue[i]}', ha='center', va='center')plt.text(i, cum_height[i][1]+cost[i]/2, f'{cost[i]}', ha='center', va='center')plt.text(i, cum_height[i][2]+profit[i]/2, f'{profit[i]}', ha='center', va='center')plt.legend(loc='upper left')
plt.title('季度财务数据堆叠面积图')
plt.ylabel('金额(万元)')
plt.show()

平滑曲线堆叠面积图

from scipy.interpolate import make_interp_spline# 原始数据
x = np.array([1, 2, 3, 4, 5])
y1 = np.array([2, 3, 5, 7, 6])
y2 = np.array([3, 4, 6, 4, 7])# 创建平滑曲线
x_smooth = np.linspace(x.min(), x.max(), 300)
spl1 = make_interp_spline(x, y1, k=3)
spl2 = make_interp_spline(x, y2, k=3)
y1_smooth = spl1(x_smooth)
y2_smooth = spl2(x_smooth)# 绘制平滑的堆叠面积图
plt.stackplot(x_smooth, y1_smooth, y2_smooth,labels=['系列A', '系列B'],colors=['#FF9AA2', '#FFB7B2'],alpha=0.8)# 添加原始数据点
plt.scatter(x, y1, color='#FF5D73', zorder=3)
plt.scatter(x, y2+y1, color='#D81159', zorder=3)plt.legend(loc='upper left')
plt.title('平滑曲线堆叠面积图')
plt.show()

时间序列堆叠面积图

import pandas as pd# 创建时间序列数据
date_rng = pd.date_range(start='2023-01-01', end='2023-12-31', freq='M')
categories = ['电子产品', '家居用品', '服装']
data = np.random.randint(10, 50, size=(len(date_rng), len(categories)))
df = pd.DataFrame(data, index=date_rng, columns=categories)# 绘制时间序列堆叠面积图
plt.stackplot(df.index, df['电子产品'], df['家居用品'], df['服装'],labels=categories,colors=['#7BC8F6', '#FF7373', '#FFA500'])plt.legend(loc='upper left')
plt.title('2023年各月销售额分布')
plt.ylabel('销售额(万元)')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
1.2:等高线图contour/contourf

等高线图是用于可视化三维数据的二维表示方法,通过等高线展示数据的分布特征。Matplotlib提供contour和contourf两种函数来绘制等高线图,前者绘制线条,后者填充颜色区域。

基本等高线图(contour)

contour函数的基本使用需要三个二维数组:X,Y坐标网格和Z值数据。创建方法如下:

import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as np# plt.rcParams['font.sans-serif'] = ['PingFang']  # Windows系统使用黑体
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsedef grid_spec_test():# 生成地形数据x = np.linspace(-5, 5, 100)y = np.linspace(-5, 5, 100)X, Y = np.meshgrid(x, y)Z = np.sin(np.sqrt(X ** 2 + Y ** 2))  # 圆形波浪地形# 绘制地形plt.figure(figsize=(10, 6))# 通过contourf绘制等值线图cf = plt.contourf(X, Y, Z, levels=20, cmap='terrain')c = plt.contour(X, Y, Z, levels=20, colors='black', linewidths=0.5)plt.clabel(c, inline=True, fontsize=8)plt.colorbar(cf, label='高度')plt.title('地形高度图')plt.xlabel('经度')plt.ylabel('纬度')plt.show()if __name__ == '__main__':grid_spec_test()

在这里插入图片描述
contour会自动选择等高线的数量和位置,也可以通过levels参数手动指定:

# 指定10条等高线
plt.contour(X, Y, Z, levels=10)# 指定具体等高线位置
plt.contour(X, Y, Z, levels=[0.1, 0.3, 0.5, 0.7, 0.9])

填充等高线图(contourf)

contourf会填充等高线之间的区域,比contour更直观:

plt.contourf(X, Y, Z, levels=10, cmap='RdYlBu')  # 使用红-黄-蓝色图
plt.colorbar()
plt.title('填充等高线图')
plt.show()

可以同时使用contour和contourf增强可视化效果:

# 先绘制填充
cf = plt.contourf(X, Y, Z, levels=10, cmap='coolwarm')# 再绘制等高线
c = plt.contour(X, Y, Z, levels=10, colors='black', linewidths=0.5)# 添加等高线标签
plt.clabel(c, inline=True, fontsize=8)plt.colorbar(cf)
plt.title('组合等高线图')
plt.show()

高级定制选项

线型和颜色

对于contour图,可以自定义线型和颜色:

# 不同等高线使用不同颜色和线型
CS = plt.contour(X, Y, Z, levels=5, colors=('r', 'g', 'b', 'c', 'm'),linestyles=('--', '-.', '-', ':', '--'))
plt.clabel(CS, fmt='%1.1f')  # 格式化标签

透明度设置

可以设置填充区域的透明度:

plt.contourf(X, Y, Z, levels=10, alpha=0.6)
plt.contour(X, Y, Z, levels=10, colors='k', linewidths=0.5)

不等间距等高线

可以创建不等间距的等高线来突出特定区域:

levels = [0, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0]
plt.contourf(X, Y, Z, levels=levels, extend='both')  # extend允许超出范围
plt.colorbar()

实际应用示例

地形高度

# 生成地形数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))  # 圆形波浪地形# 绘制地形
plt.figure(figsize=(10, 6))
cf = plt.contourf(X, Y, Z, levels=20, cmap='terrain')
c = plt.contour(X, Y, Z, levels=20, colors='black', linewidths=0.5)
plt.clabel(c, inline=True, fontsize=8)
plt.colorbar(cf, label='高度')
plt.title('地形高度图')
plt.xlabel('经度')
plt.ylabel('纬度')
plt.show()

温度分布图

# 生成温度数据
x = np.linspace(0, 24, 100)
y = np.linspace(0, 30, 100)
X, Y = np.meshgrid(x, y)
Z = 20 + 10*np.sin(X/2) + 5*np.cos(Y/6)  # 模拟昼夜和季节变化# 绘制温度分布
plt.figure(figsize=(10, 6))
cf = plt.contourf(X, Y, Z, levels=np.linspace(5, 35, 13), cmap='jet')
c = plt.contour(X, Y, Z, levels=np.linspace(5, 35, 13), colors='k', linewidths=0.5)
plt.clabel(c, inline=True, fmt='%1.0f°C')
plt.colorbar(cf, label='温度 (°C)')
plt.title('温度时空分布')
plt.xlabel('时间 (小时)')
plt.ylabel('天数')
plt.show()

数学函数可视化

# 定义复杂函数
def f(x, y):return np.sin(x) * np.cos(y) + np.sin(y/2) * np.cos(x/3)# 生成数据
x = np.linspace(-2*np.pi, 2*np.pi, 200)
y = np.linspace(-2*np.pi, 2*np.pi, 200)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)# 绘制函数图像
plt.figure(figsize=(10, 8))
plt.contourf(X, Y, Z, levels=20, cmap='coolwarm')
plt.contour(X, Y, Z, levels=20, colors='k', linewidths=0.3)
plt.colorbar(label='函数值')
plt.title('复杂函数 f(x,y) = sin(x)cos(y) + sin(y/2)cos(x/3)')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()

常见问题解决

  1. 锯齿状等高线:增加网格密度(np.linspace点数)
  2. 颜色条范围不合适:使用vmin/vmax参数手动设置范围
  3. 标签重叠:调整fmt格式或使用manual参数手动放置
  4. 内存不足:对于大数据集,减少网格点数或使用pcolormesh
  5. 数值范围过大:考虑对数据取对数(np.log)后再绘图
1.3:3D 绘图mplot3d

Matplotlib的mplot3d工具包提供了丰富多样的三维数据可视化功能,可以创建各种类型的三维图表

方法一:首先可以使用projection="3d"直接构建3d效果,可以拖动

import matplotlib.pyplot as plt
import numpy as np
# from mpl_toolkits.mplot3d import Axes3D# plt.rcParams['font.sans-serif'] = ['PingFang']  # Windows系统使用黑体
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsedef grid_spec_test():# 创建图形和三维坐标轴fig = plt.axes(projection="3d")x = np.linspace(-5, 5, 100)y = np.linspace(-5, 5, 100)# 生成网格X, Y = np.meshgrid(x, y)# 计算Z, 创建三维曲面Z = np.sin(np.sqrt(X ** 2 + Y ** 2))# 绘制fig.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow')plt.show()if __name__ == '__main__':grid_spec_test()

在这里插入图片描述

方式二:使用Axes3D子图实现

# 创建画布,并在画布上创建对应的3D子图
fig = plt.figure()
ax = Axes3D(fig)
...
1.4:极坐标图polar

极坐标图是一种在极坐标系(半径和角度)而非笛卡尔坐标系(x和y)中绘制的图表,非常适合展示周期性或方向性数据。

要创建极坐标图,需要在创建子图时指定polar=True参数

import numpy as np
import matplotlib.pyplot as plt# 创建极坐标图
ax = plt.subplot(111, polar=True)# 生成数据
theta = np.linspace(0, 2*np.pi, 100)  # 角度
r = np.abs(np.sin(5*theta))  # 半径# 绘制极坐标线图
ax.plot(theta, r)plt.title('基本极坐标图')
plt.show()

在这里插入图片描述

主要极坐标图表类型

极坐标线图:

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)# 生成更复杂的数据
theta = np.linspace(0, 2*np.pi, 200)
r1 = 1 + 0.3*np.sin(8*theta)
r2 = 0.8 + 0.2*np.cos(12*theta)# 绘制多条极坐标曲线
ax.plot(theta, r1, label='曲线1', lw=2)
ax.plot(theta, r2, label='曲线2', ls='--', lw=2)# 设置图例位置(转换为极坐标位置)
ax.legend(bbox_to_anchor=(1.1, 1.1))plt.title('极坐标线图')
plt.show()

在这里插入图片描述

极坐标散点图:

plt.figure(figsize=(8, 6))
ax = plt.subplot(111, polar=True)# 生成随机数据
theta = np.random.uniform(0, 2*np.pi, 50)
r = np.random.uniform(0, 1, 50)
colors = theta  # 使用角度值作为颜色
sizes = 100 * r**2  # 使用半径值决定点大小# 绘制极坐标散点图
sc = ax.scatter(theta, r, c=colors, s=sizes, cmap='hsv', alpha=0.7)# 添加颜色条
plt.colorbar(sc, label='角度值')plt.title('极坐标散点图')
plt.show()

在这里插入图片描述

极坐标柱状图(风玫瑰图):

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)# 生成数据 - 16个方向的频率
directions = np.linspace(0, 2*np.pi, 16, endpoint=False)
frequencies = np.random.randint(1, 10, 16)
width = 2*np.pi/16 * 0.8  # 柱宽# 绘制极坐标柱状图
bars = ax.bar(directions, frequencies, width=width, bottom=0.0, alpha=0.7, color=plt.cm.viridis(frequencies/10))# 设置角度刻度
ax.set_xticks(directions)
ax.set_xticklabels(['N', '', 'NE', '', 'E', '', 'SE', '', 'S', '', 'SW', '', 'W', '', 'NW', ''])plt.title('风玫瑰图(极坐标柱状图)')
plt.show()

在这里插入图片描述

极坐标填充图:

plt.figure(figsize=(8, 6))
ax = plt.subplot(111, polar=True)theta = np.linspace(0, 2*np.pi, 100)
r = 2 + np.sin(5*theta)# 填充极坐标曲线下方的区域
ax.fill(theta, r, 'skyblue', alpha=0.6)
ax.plot(theta, r, 'b-', lw=2)plt.title('极坐标填充图')
plt.show()

高级极坐标图定制

极坐标网格和刻度定制:

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)theta = np.linspace(0, 2*np.pi, 100)
r = np.exp(0.1*theta)ax.plot(theta, r)# 自定义径向网格和标签
ax.set_rgrids([1, 2, 3, 4, 5], angle=45, labels=['1x', '2x', '3x', '4x', '5x'],color='gray', linestyle='--')# 自定义角度网格
ax.set_thetagrids(np.arange(0, 360, 45), labels=np.arange(0, 360, 45))# 设置径向范围
ax.set_rlim(0, 6)plt.title('自定义网格的极坐标图')
plt.show()

多极坐标子图:

fig = plt.figure(figsize=(12, 6))# 第一个子图
ax1 = fig.add_subplot(121, polar=True)
theta = np.linspace(0, 2*np.pi, 100)
r1 = np.abs(np.sin(3*theta))
ax1.plot(theta, r1)
ax1.set_title('3叶玫瑰线')# 第二个子图
ax2 = fig.add_subplot(122, polar=True)
r2 = np.abs(np.cos(4*theta))
ax2.plot(theta, r2, color='red')
ax2.set_title('4叶玫瑰线')plt.tight_layout()
plt.show()

极坐标等高线图:

fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, polar=True)# 生成网格数据
theta = np.linspace(0, 2*np.pi, 100)
r = np.linspace(0, 3, 100)
T, R = np.meshgrid(theta, r)
Z = ((R**2 - 1)**2)# 绘制极坐标等高线图
contour = ax.contour(T, R, Z, levels=10, cmap='rainbow')# 添加标签
ax.clabel(contour, inline=True, fontsize=8)plt.title('极坐标等高线图')
plt.show()

实际应用示例

雷达图(蜘蛛网图):

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D# plt.rcParams['font.sans-serif'] = ['PingFang']  # Windows系统使用黑体
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsedef grid_spec_test():fig = plt.figure(figsize=(8, 6))ax = fig.add_subplot(111, polar=True)# 数据 - 五个维度的评分categories = ['速度', '力量', '技巧', '防守', '耐力']values1 = [4, 3, 5, 2, 4]values2 = [3, 4, 2, 3, 4]N = len(categories)# 闭合数据values1 += values1[:1]angles1 = np.linspace(0, 2 * np.pi, N, endpoint=False).tolist()angles1 += angles1[:1]values2 += values2[:1]angles2 = np.linspace(0, 2 * np.pi, N, endpoint=False).tolist()angles2 += angles2[:1]# 绘制雷达图ax.plot(angles1, values1, 'b-', linewidth=2, label='球员A')ax.fill(angles1, values1, 'b', alpha=0.2)ax.plot(angles2, values2, 'r-', linewidth=2, label='球员B')ax.fill(angles2, values2, 'r', alpha=0.2)# 设置角度刻度ax.set_xticks(angles1[:-1])ax.set_xticklabels(categories1)ax.set_xticks(angles2[:-1])ax.set_xticklabels(categories2)# 设置径向刻度ax.set_yticks([1, 2, 3, 4, 5])ax.set_ylim(0, 5)plt.title('运动员能力雷达图')plt.legend(loc='upper right')plt.show()if __name__ == '__main__':grid_spec_test()

在这里插入图片描述

24小时极坐标时钟图:

fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, polar=True)# 生成24小时数据
hours = np.linspace(0, 2*np.pi, 24, endpoint=False)
activity = np.random.randint(1, 10, 24)# 绘制柱状图
bars = ax.bar(hours, activity, width=2*np.pi/24*0.8,color=plt.cm.plasma(activity/10),edgecolor='k')# 设置时钟样式
ax.set_theta_zero_location('N')  # 0度在顶部
ax.set_theta_direction(-1)  # 顺时针方向
ax.set_xticks(hours)
ax.set_xticklabels(range(24))
ax.set_rgrids([2, 4, 6, 8], angle=0)plt.title('24小时活动极坐标图')
plt.show()

在这里插入图片描述

常见问题与技巧

  1. 角度方向控制

    ax.set_theta_direction(-1)  # 顺时针方向
    ax.set_theta_zero_location('N')  # 0度在顶部
    
  2. 径向标签位置

    ax.set_rlabel_position(135)  # 径向标签放在135度位置
    
  3. 极坐标与笛卡尔坐标转换

    # 极坐标转笛卡尔坐标
    x = r * np.cos(theta)
    y = r * np.sin(theta)
    
  4. 处理负半径值

    • 负半径会显示在相反方向的角度上
    • 可以使用np.abs()处理数据,如果不需要这种特性
  5. 极坐标图保存

    plt.savefig('polar_plot.png', dpi=300, bbox_inches='tight', transparent=True)
    

极坐标图是展示周期性数据、方向性数据和多变量比较的理想选择。通过合理设置角度、径向参数以及颜色映射,可以创建出信息丰富且美观的可视化图表。

1.5:热力图imshow/pcolor

热力图是一种用颜色矩阵展示数据值的二维可视化方法,Matplotlib提供了imshowpcolor两种主要函数来创建热力图

imshow是最常用的热力图函数,适合显示规则的二维数组数据:

import numpy as np
import matplotlib.pyplot as plt# 创建数据(10x10的随机矩阵)
data = np.random.rand(10, 10)# 基础热力图
plt.figure(figsize=(8, 6))
plt.imshow(data)
plt.colorbar()  # 添加颜色条
plt.title('基础imshow热力图')
plt.show()
plt.imshow(data,cmap='viridis',      # 颜色映射interpolation='nearest',  # 插值方式aspect='auto',       # 纵横比('auto','equal',数字)origin='upper',      # 原点位置('upper','lower')vmin=0, vmax=1,      # 颜色范围限制alpha=0.8)           # 透明度

pcolor和更高效的pcolormesh适合非均匀网格数据:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D# plt.rcParams['font.sans-serif'] = ['PingFang']  # Windows系统使用黑体
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsedef grid_spec_test():# 创建非均匀网格数据x = np.arange(0, 10, 1)y = np.arange(0, 15, 1.5)X, Y = np.meshgrid(x, y)Z = np.sin(X) + np.cos(Y)# pcolormesh绘图plt.figure(figsize=(10, 6))plt.pcolormesh(X, Y, Z,shading='auto',  # 着色方式('auto','flat','gouraud')cmap='coolwarm')plt.colorbar(label='数值')plt.title('pcolormesh热力图')plt.xlabel('X轴')plt.ylabel('Y轴')plt.show()if __name__ == '__main__':grid_spec_test()

在这里插入图片描述

2:动画和交互

2.1:基本动画

Matplotlib的动画功能主要通过animation模块实现,可以创建各种动态可视化效果。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation# 创建图形和坐标轴
fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 2*np.pi, 200)
line, = ax.plot(x, np.sin(x))
ax.set_ylim(-1.5, 1.5)# 动画更新函数
def update(frame):line.set_ydata(np.sin(x + frame/10))  # 更新y数据return line,# 创建动画
ani = FuncAnimation(fig, update, frames=100, interval=50, blit=True)plt.title('正弦波动画')
plt.show()

可以保存为gif或者mp4

# 保存为GIF需要安装pillow
ani.save('sine_wave.gif', writer='pillow', fps=20, dpi=100)# 保存为MP4需要安装ffmpeg
ani.save('sine_wave.mp4', writer='ffmpeg', fps=20, bitrate=1800, dpi=100)
2.2:交互式绘图

缩放和平移

plt.ion()  # 开启交互模式fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.legend()
# 交互功能会自动启用
plt.title('可缩放平移的图表 (尝试用鼠标操作)')
plt.ioff()  # 关闭交互模式
plt.show()

数据光标功能

from matplotlib.widgets import Cursorfig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax.plot(x, y)
# 添加十字光标
cursor = Cursor(ax, horizOn=True, vertOn=True, color='red', linewidth=1)plt.title('带数据光标的图表 (鼠标移动查看坐标)')
plt.show()

交互式标记点

class ClickMarker:def __init__(self, ax):self.ax = axself.xs, self.ys = [], []self.line, = ax.plot([], [], 'ro', ms=8)self.cid = fig.canvas.mpl_connect('button_press_event', self)def __call__(self, event):if event.inaxes != self.ax: returnself.xs.append(event.xdata)self.ys.append(event.ydata)self.line.set_data(self.xs, self.ys)fig.canvas.draw()fig, ax = plt.subplots(figsize=(8, 5))
ax.set_xlim(0, 10); ax.set_ylim(-2, 2)
ax.plot(np.linspace(0, 10, 100), np.sin(np.linspace(0, 10, 100)))click = ClickMarker(ax)
plt.title('点击图表添加标记点')
plt.show()

交互式控件

from matplotlib.widgets import Slider, Button
import matplotlib.pyplot as plt
import numpy as np# plt.rcParams['font.sans-serif'] = ['PingFang']  # Windows系统使用黑体
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # macOS系统
# plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']  # Linux系统或通用方案# 解决负号('-')显示为方块的问题
plt.rcParams['axes.unicode_minus'] = Falsefig, (ax, slider_ax) = plt.subplots(2, 1, figsize=(8, 6),gridspec_kw={'height_ratios': [4, 1]})x = np.linspace(0, 2*np.pi, 200)
freq_init = 1.0
line, = ax.plot(x, np.sin(freq_init * x))
ax.set_ylim(-1.5, 1.5)# 创建滑块
slider = Slider(slider_ax, '频率', 0.1, 5.0, valinit=freq_init)def update(val):freq = slider.valline.set_ydata(np.sin(freq * x))fig.canvas.draw_idle()slider.on_changed(update)# 添加重置按钮
reset_ax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(reset_ax, '重置')def reset(event):slider.reset()button.on_clicked(reset)plt.title('带交互控件的图表')
plt.tight_layout()
plt.show()
2.3:事件处理

Matplotlib提供了完善的事件处理系统,可以捕获并响应各种用户交互事件。

键盘事件处理

def on_key(event):print(f'你按下了: {event.key}')if event.key == 'escape':plt.close(event.canvas.figure)fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(np.random.rand(10))fig.canvas.mpl_connect('key_press_event', on_key)
plt.title('尝试按键盘按键 (ESC键退出)')
plt.show()

鼠标事件处理

def on_move(event):if event.inaxes:print(f'鼠标位置: x={event.xdata:.2f}, y={event.ydata:.2f}')def on_click(event):if event.inaxes:print(f'在位置 ({event.xdata:.2f}, {event.ydata:.2f}) 点击了 {event.button} 键')fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(np.random.rand(10))fig.canvas.mpl_connect('motion_notify_event', on_move)
fig.canvas.mpl_connect('button_press_event', on_click)
plt.title('移动鼠标和点击查看事件')
plt.show()

自定义选取区域

class RegionSelector:def __init__(self, ax):self.ax = axself.start = Noneself.rect = Noneself.cid_press = fig.canvas.mpl_connect('button_press_event', self.on_press)self.cid_release = fig.canvas.mpl_connect('button_release_event', self.on_release)def on_press(self, event):if event.inaxes != self.ax: returnself.start = (event.xdata, event.ydata)self.rect = plt.Rectangle((event.xdata, event.ydata), 0, 0, fill=False, edgecolor='red', linewidth=2)self.ax.add_patch(self.rect)def on_release(self, event):if self.start is None: returnx0, y0 = self.startx1, y1 = event.xdata, event.ydatawidth = x1 - x0height = y1 - y0print(f'选取区域: x={min(x0,x1):.2f}-{max(x0,x1):.2f}, y={min(y0,y1):.2f}-{max(y0,y1):.2f}')self.rect.set_width(width)self.rect.set_height(height)fig.canvas.draw()self.start = Nonefig, ax = plt.subplots(figsize=(8, 5))
ax.plot(np.random.rand(100))selector = RegionSelector(ax)
plt.title('鼠标拖拽选取区域')
plt.show()

复杂事件处理示例

class InteractivePlot:def __init__(self):self.fig, self.ax = plt.subplots(figsize=(10, 6))self.x = np.linspace(0, 10, 100)self.line, = self.ax.plot(self.x, np.sin(self.x))self.fig.canvas.mpl_connect('key_press_event', self.on_key)self.fig.canvas.mpl_connect('scroll_event', self.on_scroll)self.freq = 1.0self.amp = 1.0self.ax.set_title("使用↑↓调整频率(当前:1.0), 滚轮调整振幅(当前:1.0)")def on_key(self, event):if event.key == 'up':self.freq += 0.1elif event.key == 'down':self.freq -= 0.1self.update_plot()def on_scroll(self, event):if event.button == 'up':self.amp += 0.1elif event.button == 'down':self.amp -= 0.1self.update_plot()def update_plot(self):self.line.set_ydata(self.amp * np.sin(self.freq * self.x))self.ax.set_title(f"使用↑↓调整频率(当前:{self.freq:.1f}), 滚轮调整振幅(当前:{self.amp:.1f})")self.fig.canvas.draw()interactive_plot = InteractivePlot()
plt.show()
http://www.dtcms.com/a/275821.html

相关文章:

  • 9.2 埃尔米特矩阵和酉矩阵
  • Go内存分配
  • linux系统mysql性能优化
  • 【Modern C++ Part9】Prefer-alias-declarations-to-typedefs
  • Opencv---深度学习开发
  • 云计算三大服务模式深度解析:IaaS、PaaS、SaaS
  • 【数据结构与算法】数据结构初阶:详解顺序表和链表(四)——单链表(下)
  • 【PTA数据结构 | C语言版】后缀表达式求值
  • Transforms
  • Spring(四) 关于AOP的源码解析与思考
  • 一文理解缓存的本质:分层架构、原理对比与实战精粹
  • 别再怕 JSON!5分钟带你轻松搞懂这个程序员的好帮手
  • 鸿蒙的NDK开发初级入门篇
  • RISC-V:开源芯浪潮下的技术突围与职业新赛道 (四) 产业应用全景扫描
  • (LeetCode 面试经典 150 题 ) 209. 长度最小的子数组(双指针)
  • Ntfs!LfsFlushLfcb函数分析之while的循环条件NextLbcb的确定和FirstLbcb->LbcbFlags的几种情况
  • docker-compose方式搭建lnmp环境——筑梦之路
  • 【android bluetooth 协议分析 07】【SDP详解 2】【SDP 初始化】
  • Operation Blackout 2025: Smoke Mirrors
  • Windows符号链接解决vscode和pycharm占用C盘空间太大的问题
  • NX二次开发——导入模型是常遇见的问题(导入模型原点的确定导入模型坐标的确定)
  • BERT:双向Transformer革命 | 重塑自然语言理解的预训练范式
  • 深入理解大语言模型:从核心技术到极简实现
  • 洛谷题解 | UVA1485 Permutation Counting
  • jenkins自动化部署前端vue+docker项目
  • 前端面试宝典---项目难点2-智能问答对话框采用虚拟列表动态渲染可视区域元素(10万+条数据)
  • 自动化运维工具jenkins问题
  • Ubuntu安装Jenkins
  • java堆的创建与基础代码解析(图文)
  • Classifier guidance与Classifier-free guidance的原理和公式推导