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

python | numpy小记(八):理解 NumPy 中的 `np.meshgrid`

python | numpy小记(八):理解 NumPy 中的 `np.meshgrid`

      • 一、核心思想:从“轴”到“网”
      • 二、工作原理与详细示例
      • 三、为什么它如此有用?——矢量化计算
      • 四、进阶用法
        • 1. 绘制三维曲面和等高线图
        • 2. `indexing` 参数
      • 总结


一、核心思想:从“轴”到“网”

想象一下,你正在一张白纸上画一个坐标网格。

  1. 首先,你在 x 轴(横轴)上标记了几个点,比如 x = [1, 2, 3]
  2. 然后,你在 y 轴(纵轴)上标记了几个点,比如 y = [10, 20, 30, 40]

现在,这些标记的点定义了一个网格。这个网格上有很多交叉点,它们的坐标分别是:
(1, 10), (2, 10), (3, 10)
(1, 20), (2, 20), (3, 20)
(1, 30), (2, 30), (3, 30)
(1, 40), (2, 40), (3, 40)

现在问题来了:如果我想对每一个网格点进行计算(比如计算 z = f(x, y)),我需要一种方法来轻松地获取每个点的 xy 坐标。

numpy.meshgrid 的作用就是帮你解决这个问题。它接收代表坐标轴上点的一维向量(如上面的 xy),然后生成两个二维矩阵(我们通常称之为 XXYY)。这两个矩阵包含了网格上每个点的x坐标和y坐标。

  • XX 矩阵:存储了网格中每一个点x 坐标
  • YY 矩阵:存储了网格中每一个点y 坐标

二、工作原理与详细示例

让我们用上面那个简单的例子来看看 meshgrid 是如何工作的。

import numpy as np# 1. 定义x轴和y轴上的点
x = np.array([1, 2, 3])      # 长度为 3
y = np.array([10, 20, 30, 40]) # 长度为 4# 2. 使用 meshgrid 生成坐标矩阵
XX, YY = np.meshgrid(x, y)# 3. 打印输出,观察结果
print("原始 x 向量:\n", x)
print("原始 y 向量:\n", y)
print("-" * 20)
print("生成的 XX 矩阵 (x-coordinates):\n", XX)
print("XX 矩阵的形状:", XX.shape)
print("-" * 20)
print("生成的 YY 矩阵 (y-coordinates):\n", YY)
print("YY 矩阵的形状:", YY.shape)

输出结果:

原始 x 向量:[1 2 3]
原始 y 向量:[10 20 30 40]
--------------------
生成的 XX 矩阵 (x-coordinates):[[1 2 3][1 2 3][1 2 3][1 2 3]]
XX 矩阵的形状: (4, 3)
--------------------
生成的 YY 矩阵 (y-coordinates):[[10 10 10][20 20 20][30 30 30][40 40 40]]
YY 矩阵的形状: (4, 3)

结果分析:

  • XX 矩阵的构建meshgrid 将原始的 x 向量 [1, 2, 3] 水平地复制了 len(y) 次(也就是4次),像叠煎饼一样垂直叠起来,形成一个 (4, 3) 的矩阵。所以,XX 的每一行都是 [1, 2, 3]
  • YY 矩阵的构建meshgrid 将原始的 y 向量 [10, 20, 30, 40] 垂直地复制了 len(x) 次(也就是3次),像手风琴一样水平拉开,形成一个 (4, 3) 的矩阵。所以,YY 的每一列都是 [10, 20, 30, 40]

最关键的一点是:现在 XXYY 在相同位置 (i, j) 上的值,正好对应了我们网格中第 i 行、第 j 列那个点的坐标!

例如,我们想找网格上第2行(索引为1)、第3列(索引为2)的那个点:

  • XX[1, 2] 的值是 3
  • YY[1, 2] 的值是 20
  • 所以这个点的坐标就是 (3, 20),和我们手动列出的一模一样!

三、为什么它如此有用?——矢量化计算

meshgrid 最大的优势在于它能让我们避免使用缓慢的 Python for 循环,而是利用 NumPy 的**矢量化计算(Vectorization)**能力,对整个网格进行一次性、高性能的计算。

应用场景:计算二维函数 z = sin(x) + cos(y) 在整个网格上的值。

方法一:使用 for 循环(效率低)

z_loop = np.zeros_like(XX, dtype=float) # 创建一个和XX形状相同的零矩阵for i in range(XX.shape[0]): # 遍历行for j in range(XX.shape[1]): # 遍历列z_loop[i, j] = np.sin(XX[i, j]) + np.cos(YY[i, j])# print("使用循环计算的结果:\n", z_loop)

这种方法非常直观,但当网格很大时,嵌套的Python循环会变得非常慢。

方法二:使用 meshgrid 和矢量化计算(高效)

# 因为 XX 和 YY 的形状完全相同,我们可以直接对它们进行数学运算
# NumPy 会自动对矩阵中的每一个元素执行操作
Z_vectorized = np.sin(XX) + np.cos(YY)# print("使用矢量化计算的结果:\n", Z_vectorized)

这一行代码就完成了和上面两层for循环完全一样的工作!它直接在C语言层面进行计算,速度比Python循环快几个数量级。

这就是 meshgrid 的威力所在:它为矢量化计算搭建了舞台。

四、进阶用法

1. 绘制三维曲面和等高线图

在数据可视化领域,尤其是在使用 matplotlib 库时,meshgrid 是不可或缺的。当你需要绘制一个三维曲面 z = f(x, y) 时,你需要提供 x, y, z 的坐标。这里的 xy 就必须是 meshgrid 生成的二维坐标矩阵。

import matplotlib.pyplot as pltx_surf = np.linspace(-5, 5, 100)
y_surf = np.linspace(-5, 5, 100)XX_surf, YY_surf = np.meshgrid(x_surf, y_surf)
Z_surf = np.sinc(np.sqrt(XX_surf**2 + YY_surf**2)) # 计算一个二维sinc函数fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(XX_surf, YY_surf, Z_surf, cmap='viridis')
plt.title("3D Surface Plot using meshgrid")
plt.show()
2. indexing 参数

meshgrid 有一个重要的参数 indexing,它有两个值:'xy' (默认值) 和 'ij'

  • indexing='xy'(笛卡尔坐标系索引):

    • 输出矩阵的形状是 (len(y), len(x))
    • XX 的行是 x 的拷贝,YY 的列是 y 的拷贝。
    • 这种方式最符合绘图和几何直觉。我们上面的所有例子都使用这种默认方式。
  • indexing='ij'(矩阵索引):

    • 输出矩阵的形状是 (len(x), len(y))
    • XX 的列是 x 的拷贝,YY 的行是 y 的拷贝。基本上是 'xy' 模式结果的转置。
    • 这种方式在进行纯粹的矩阵和数组运算时可能更自然。
XX_ij, YY_ij = np.meshgrid(x, y, indexing='ij')print("XX 矩阵 (indexing='ij'):\n", XX_ij)
print("XX_ij 的形状:", XX_ij.shape)
print("-" * 20)
print("YY 矩阵 (indexing='ij'):\n", YY_ij)
print("YY_ij 的形状:", YY_ij.shape)

输出:

XX 矩阵 (indexing='ij'):[[1 1 1 1][2 2 2 2][3 3 3 3]]
XX_ij 的形状: (3, 4)
--------------------
YY 矩阵 (indexing='ij'):[[10 20 30 40][10 20 30 40][10 20 30 40]]
YY_ij 的形状: (3, 4)

可以看到,输出矩阵的形状和值的排布都发生了变化。了解这个参数对于避免在复杂计算中出错非常重要。

总结

  1. 核心功能np.meshgrid 从一维的坐标轴向量生成二维(或多维)的坐标网格矩阵。
  2. 主要目的:为矢量化计算服务,让你能够对整个网格上的所有点进行快速、高效的并行计算,避免使用慢速的Python循环。
  3. 经典应用:计算二维/三维函数在网格上的值、生成数据用于绘制等高线图和三维表面图。
  4. 注意事项:留意 indexing 参数 ('xy' vs 'ij'),确保它符合你的计算或绘图需求。
http://www.xdnf.cn/news/1214227.html

相关文章:

  • 嵌入式linux驱动开发:什么是Linux驱动?深度解析与实战入门
  • 如何通过IT-Tools与CPolar构建无缝开发通道?
  • OriGene:一种可自进化的虚拟疾病生物学家,实现治疗靶点发现自动化
  • 【ESP32设备通信】-LAN8720与ESP32集成
  • MOEA/DD与MOEA/D的区别
  • 2024 年 NOI 最后一题题解
  • 算法精讲:二分查找(二)—— 变形技巧
  • 【Excel】制作双重饼图
  • 关于windows虚拟机无法联网问题
  • VMware16安装Ubuntu-22.04.X版本(并使用桥接模式实现局域网下使用ssh远程操作Ubuntu系统)
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-51,(知识点:stm32,GPIO基础知识)
  • C++菱形虚拟继承:解开钻石继承的魔咒
  • 简单线性回归模型原理推导(最小二乘法)和案例解析
  • 线性回归的应用
  • 明智运用C++异常规范(Exception Specifications)
  • 爬虫验证码处理:ddddocr 的详细使用(通用验证码识别OCR pypi版)
  • 架构实战——架构重构内功心法第一式(有的放矢)
  • 地图可视化实践录:显示高德地图和百度地图
  • Linux 进程管理与计划任务详解
  • 关于神经网络CNN的搭建过程以及图像卷积的实现过程学习
  • Mac下的Homebrew
  • 如何不让android studio自动换行
  • cpp c++面试常考算法题汇总
  • 高防CDN与高防IP的选择
  • 【ip】IP地址能否直接填写255?
  • SpringBoot升级2.5.3 2.6.8
  • gtest框架的安装与使用
  • 基于成像空间转录组技术的肿瘤亚克隆CNV原位推断方法
  • android-PMS-创建新用户流程
  • VUE -- 基础知识讲解(三)