numpy中数组和矩阵的索引方法及不同点

本文探讨了NumPy中数组和矩阵之间的关键区别,包括它们的索引方式、切片行为以及如何通过布尔索引进行条件切片。文章还详细说明了如何在数组和矩阵上获得一致的切片结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NumPy中数组和矩阵有些重要的区别:
NumPy提供了两个基本的对象:一个N维数组对象和一个通用函数对象。其它对象都是建构在它们之上的。特别的,矩阵是继承自NumPy数组对象的二维数组对象。像平常在Python中一样,索引是从0开始的。传统上我们用矩形的行和列表示一个二维数组或矩阵,其中二维矩阵或数组的行方向为第0轴(竖轴),列方向为第1轴(横轴)。
注:他们的索引一般都采用一维数组或者布尔值组成的数组,而不采用列表或其他序列!基本的切片使用切片对象或整数。例如,A[:]和M[:]的求值将表现得和Python索引很相似。然而要注意很重要的一点就是NumPy切片数组不创建数据的副本;切片提供统一数据的视图。

创建数组和矩阵用来切片:此处的复制为深复制,A为数组,M为矩阵

>>> A = arange(12)
>>> A
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> A.shape = (3,4)
>>> M = mat(A.copy())
>>> print type(A),"  ",type(M)

>>> print A
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
>>> print M
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]] 

重要不同是:

对于数组:
>>> print A[:,1]; print A[:,1].shape
[1 5 9]
(3,)
对于矩阵:
>>> print M[:,1]; print M[:,1].shape
[[1]
 [5]
 [9]]
(3, 1) 

最后两个结果的不同:对二维数组使用一个冒号产生一个一维数组,然而矩阵产生了一个二维矩阵。例如,一个M[2,:]切片产生了一个形状为(1,4)的矩阵,相比之下,一个数组的切片总是产生一个最低可能维度11的数组。例如,如果C是一个三维数组,C[…,1]产生一个二维的数组而C[1,:,1]产生一个一维数组。

那么怎样让数组和矩阵得到的切片结果相同呢?
比如说我们想要保留第一行大于1的列。一种方法是创建布尔索引:

>>> A[0,:]>1
array([False, False, True, True], dtype=bool)
>>> A[:,A[0,:]>1]
array([[ 2,  3],
       [ 6,  7],
       [10, 11]]) 

就是我们想要的!但是索引矩阵没这么方便。

>>> M[0,:]>1
matrix([[False, False, True, True]], dtype=bool)
>>> M[:,M[0,:]>1]
matrix([[2, 3]]) 

这个过程的问题是用“矩阵切片”来切片产生一个矩阵,但是矩阵有个方便的A属性,它的值是数组呈现的。所以我们仅仅做以下替代来得到和数组相同的切片结果:

>>> M[:,M.A[0,:]>1]
matrix([[ 2,  3],
        [ 6,  7],
        [10, 11]]) 

如果我们想要在矩阵两个方向有条件地切片,我们必须稍微调整策略,代之以:

>>> A[A[:,0]>2,A[0,:]>1]
array([ 6, 11])
>>> M[M.A[:,0]>2,M.A[0,:]>1]
matrix([[ 6, 11]]) 
<think>我们正在讨论numpy中meshgrid函数的indexing参数,其可选值为'xy'(默认)'ij'。这个参数决定了生成的网格数组索引顺序。 根据引用[1]引用[3]: - 当indexing='xy'(默认)时,生成的网格数组的第一个维度对应第二个输入数组(通常表示y坐标),第二个维度对应第一个输入数组(通常表示x坐标)。也就是说,对于两个一维数组xy,调用`X, Y = np.meshgrid(x, y, indexing='xy')`,则X的形状为(len(y), len(x)),Y的形状也是(len(y), len(x))。这种排列方式是为了符合笛卡尔坐标系中通常将x视为横坐标,y视为纵坐标的习惯,因此在二维数组中,行对应y,列对应x。 - 当indexing='ij'时,生成的网格数组的维度顺序与输入数组的顺序一致。即第一个维度对应第一个输入数组(x),第二个维度对应第二个输入数组(y)。因此,`X, Y = np.meshgrid(x, y, indexing='ij')`得到的XY的形状都是(len(x), len(y))。 引用[3]中还给出了三维网格的例子,当使用indexing='xy'时,生成的网格数组的形状为(y的长度, x的长度, z的长度),而如果使用indexing='ij',则形状为(x的长度, y的长度, z的长度)。 引用[4]的例子也展示了默认情况下(indexing='xy')生成的网格数组的形状:对于x有3个元素,y有2个元素,则xv(对应x坐标的网格)的形状是(2,3),而yv(对应y坐标的网格)的形状也是(2,3)。注意,这里xv的第一维是y的长度,第二维是x的长度。 另外,引用[1]提到,如果没有指定indexing='ij',那么meshgrid会改变参数的顺序,即相当于J, I = np.meshgrid(j, i),这里J对应y方向,I对应x方向,形成“xy”模式。 总结: - indexing='xy':生成网格的维度顺序为(y, x)在二维中,即行数由y决定,列数由x决定。这样在绘图时,可以直接用XY作为横纵坐标,符合通常的坐标系(横轴x,纵轴y)。 - indexing='ij':生成网格的维度顺序为(x, y),即行数由x决定,列数由y决定。这种顺序与数学中矩阵索引的习惯(先第i行,再第j列)一致,但注意在二维坐标系中,x通常对应列,y对应行,所以这种模式下,如果我们把第一个维度作为行,那么实际上x方向变成了行方向,y方向变成了列方向,与坐标系习惯不同。 因此,选择哪种方式取决于你的应用场景: - 如果你要使用matplotlib等库进行绘图,通常使用默认的'xy'模式,因为绘图函数期望的网格数据是这种排列。 - 如果你在处理多维数组时希望保持维度顺序与输入数组的顺序一致(即第一个输入数组对应第一个维度,第二个输入数组对应第二个维度),则使用'ij'模式。 下面用具体例子说明: 假设有两个一维数组: ```python import numpy as np x = np.array([1, 2, 3]) # 长度为3 y = np.array([4, 5]) # 长度为2 ``` 1. indexing='xy'(默认): ```python X, Y = np.meshgrid(x, y, indexing='xy') ``` 结果: X = [[1, 2, 3], [1, 2, 3]] Y = [[4, 4, 4], [5, 5, 5]] 形状:XY都是(2,3) 2. indexing='ij': ```python X, Y = np.meshgrid(x, y, indexing='ij') ``` 结果: X = [[1, 1], [2, 2], [3, 3]] Y = [[4, 5], [4, 5], [4, 5]] 形状:XY都是(3,2) 注意:在'ij'模式下,X的每一行是相同的x值,而Y的每一列是相同的y值(但这里由于形状是(3,2),所以X的每一列并不是同一个x值,而是每一行是同一个x值?实际上,在'ij'模式下,X[i,j] = x[i],Y[i,j] = y[j]。所以X的每一行是同一个x值(因为列索引j变化时,x值不变),而Y的每一列是同一个y值(因为行索引i变化时,y值不变)。 而在'xy'模式下,X[i,j] = x[j],Y[i,j] = y[i]。所以X的每一行是相同的(因为行索引i固定,j变化时取x的不同值?不对,实际上在'xy'模式下,X的每一行是相同的,因为行索引i固定,而j变化,但是X[i,j]的值等于x[j],所以同一行中j变化,x[j]就是整个x数组,因此每一行都是x数组。而Y[i,j]=y[i],所以同一列中i变化,但j固定,所以同一列是同一个y值?不对,实际上Y[i,j] = y[i]表示同一行(i固定)的所有列都是y[i]这个值,所以Y的每一行是相同的y值。 所以,在'xy'模式下,X的每一行是x数组(因为行方向是y方向,而x数组沿着列方向重复),Y的每一列是y数组?不对,实际上在'xy'模式下,X的每一行是相同的x数组,而Y的同一行是相同的y值(即该行对应的y值)。所以,X的每一行是x数组,而Y的每一行是当前行对应的y值(整个行都是这个值)。 在二维网格中,我们通常需要这样的结构:X矩阵的每个元素是那个位置的x坐标,Y矩阵的每个元素是那个位置的y坐标。在'xy'模式下,对于点(i,j)(这里i是行索引,j是列索引),其坐标是(X[i,j], Y[i,j]) = (x[j], y[i])。而在'ij'模式下,点(i,j)的坐标是(X[i,j], Y[i,j]) = (x[i], y[j])。 因此,在绘图时,我们通常希望行索引(i)对应y坐标,列索引(j)对应x坐标,所以默认的'xy'模式更直观。而'ij'模式则更符合矩阵索引的习惯(i是第一个维度,j是第二个维度),但此时点(i,j)的坐标是(x[i], y[j]),即第一个索引i对应x,第二个索引j对应y。 希望这个解释清楚了。 相关问题: 1. 在numpy的meshgrid函数中,indexing参数为'xy''ij'时,生成的数组形状有什么不同? 2. 为什么在绘制二维图形时,通常使用indexing='xy'模式? 3. 在三维网格生成中,indexing='xy''ij'会如何影响生成的网格数组的维度顺序? 4. 除了meshgrid,numpy中还有哪些函数可以生成网格?它们与meshgrid有何区别?</think>### NumPy 中 `meshgrid` 函数 `indexing` 参数详解(`'xy'` vs `'ij'`) 在 NumPy 的 `np.meshgrid()` 函数中,`indexing` 参数控制生成网格数组的维度顺序索引方式。以下是 `'xy'` `'ij'` 两种模式的核心区别: --- #### 1. **维度顺序与形状** - **`indexing='xy'`(默认模式)** 符合笛卡尔坐标系(**x 为横轴,y 为纵轴**): - **形状**:`(len(y), len(x))` - **维度顺序**:第一维是 `y`(行方向),第二维是 `x`(列方向) ```python import numpy as np x = [1, 2, 3] y = [4, 5] X, Y = np.meshgrid(x, y, indexing='xy') # 结果: # X = [[1 2 3], [1 2 3]] → 形状 (2, 3) # Y = [[4 4 4], [5 5 5]] → 形状 (2, 3) ``` - **`indexing='ij'`** 符合矩阵索引(**i 为行索引,j 为列索引**): - **形状**:`(len(x), len(y))` - **维度顺序**:第一维是 `x`(行方向),第二维是 `y`(列方向) ```python X, Y = np.meshgrid(x, y, indexing='ij') # 结果: # X = [[1 1], [2 2], [3 3]] → 形状 (3, 2) # Y = [[4 5], [4 5], [4 5]] → 形状 (3, 2) ``` --- #### 2. **物理意义与坐标系** - **`'xy'` 模式**: - 设计用于**可视化**(如 `matplotlib` 绘图)[^1][^3] - 网格点 `(i, j)` 的坐标为: $X[i,j] = x_j$(横坐标), $Y[i,j] = y_i$(纵坐标) - 示例:二维热力图、等高线图 - **`'ij'` 模式**: - 设计用于**多维数组索引**(如数值计算)[^1][^2] - 网格点 `(i, j)` 的坐标为: $X[i,j] = x_i$(第 i 个值), $Y[i,j] = y_j$(第 j 个值) - 示例:矩阵运算、张量操作 --- #### 3. **三维网格扩展** 对于三维网格(输入 `x, y, z`): - **`'xy'` 模式**:形状为 `(len(y), len(x), len(z))` - **`'ij'` 模式**:形状为 `(len(x), len(y), len(z))` ```python x = [1, 2]; y = [3, 4]; z = [5, 6] X, Y, Z = np.meshgrid(x, y, z, indexing='ij') # X.shape = (2, 2, 2) [^3] ``` --- #### 4. **何时使用哪种模式?** | **场景** | **推荐模式** | **原因** | |-------------------------|--------------|------------------------------| | 绘图(`matplotlib`) | `'xy'` | 符合 $(x, y)$ 坐标系习惯 [^5] | | 数组索引/数值计算 | `'ij'` | 对齐维度顺序(`axis=0,1,...`)[^2] | | 高维网格(如 3D 函数) | 按需选择 | 需保持输入输出维度一致性 [^3] | --- #### 5. **可视化对比** 下图展示两种模式的索引逻辑: ``` 'xy' 模式 (2D) 'ij' 模式 (2D) 列 j → x方向 行 i → x方向 行 i → y方向 列 j → y方向 (i,j) = (y_i, x_j) (i,j) = (x_i, y_j) ``` > **关键区别**:`'xy'` 交换了输入数组的顺序以适配坐标系,而 `'ij'` 严格保持输入顺序[^1][^4]。 --- ### 相关问题 1. 在三维网格生成中,`indexing='xy'` `'ij'` 会如何影响坐标数组的形状?[^3] 2. 为什么在 `matplotlib` 绘图中推荐使用 `indexing='xy'`?[^1][^5] 3. 如何利用 `np.meshgrid()` 的 `sparse=True` 参数优化内存?[^4] 4. 除了 `meshgrid`,NumPy 中还有哪些生成网格的函数(如 `mgrid`, `ogrid`)?它们与 `meshgrid` 有何区别?[^5] [^1]: 如果没有 `indexing='ij'` 参数,`meshgrid` 会交换维度顺序,即 `J, I = np.meshgrid(j, i)`,形成“xy”模式(用于可视化)。 [^2]: NumPy 的 `axis` 参数中,`axis=0` 对应第一维(如行方向),`axis=1` 对应第二维(如列方向)。 [^3]: 三维网格生成时,`indexing='xy'` 输出形状为 `(len(y), len(x), len(z))`,而 `indexing='ij'` 输出 `(len(x), len(y), len(z))`。 [^4]: 使用 `sparse=True` 可生成稀疏网格数组,减少内存占用。 [^5]: `ogrid` 生成开放网格(节省内存),`mgrid` 生成密集网格,两者索引顺序与 `meshgrid(..., indexing='ij')` 一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值