NumPy 基本切片和索引(三)

简介: ndarrays可以使用标准Python x[obj]语法对其进行索引 ,其中x是数组,obj是选择方式。有三种可用的索引:字段访问,基本切片,高级索引。究竟是哪一个取决于obj。

>>>
>>> x[1:2, 1:3]
array([[4, 5]])
>>> x[1:2, [1, 2]]
array([[4, 5]])


了解情况的最简单方法可能是考虑结果形状。索引操作分为两部分,即由基本索引(不包括整数)定义的子空间和来自高级索引部分的子空间。需要区分两种索引组合:

高级索引由切片分隔,Ellipsis或newaxis。例如。x[arr1, :, arr2]

高级索引彼此相邻。例如但不是 因为在这方面是一个高级索引。x[..., arr1, arr2, :] x[arr1, :, 1]1

在第一种情况下,高级索引操作产生的维度首先出现在结果数组中,然后是子空间维度。在第二种情况下,高级索引操作的维度将插入到结果数组中与初始数组中相同的位置(后一种逻辑使简单的高级索引行为就像切片一样)。

假设x.shape为(10,20,30)并且ind是(2,3,4)形索引intp数组,则其形状为(10,2,3,4,30),因为(20,)形子空间已被替换具有(2,3,4)形的广播索引子空间。如果我们让i,j,k循环遍及(2,3,4)形子空间 。此示例产生的结果与。result = x[...,ind,:]result[...,i,j,k,:] = x[...,ind[i,j,k],:]x.take(ind, axis=-2)

设x.shape(10,20,30,40,50)并假设ind_1 并ind_2可以广播到形状(2,3,4)。然后 x[:,ind_1,ind_2]具有形状(10,2,3,4,40,50),因为来自X的(20,30)形子空间已经被索引的(2,3,4)子空间替换。但是,它 x[:,ind_1,:,ind_2]具有形状(2,3,4,10,30,50),因为在索引子空间中没有明确的位置,所以它在开头就被添加了。始终可以使用 .transpose()在任何需要的位置移动子空间。请注意,此示例无法使用复制take。


布尔数组索引


当obj是布尔类型的数组对象时,会发生此高级索引,例如可能从比较运算符返回。x[obj.nonzero()]如上所述,单个布尔索引数组实际上与obj.nonzero()返回obj.ndim显示objTrue元素的整数索引数组的元组(长度)相同。但是,它更快。obj.shape == x.shape

如果,返回一个1维数组,该数组填充了与obj 值对应的x元素。搜索顺序为行主,C风格。如果物镜具有在该外侧是的边界的条目值X,则索引错误将被提高。如果obj小于x,则与填充它相同。obj.ndim == x.ndimx[obj]TrueTrueFalse

一个常见的用例是过滤所需的元素值。例如,可能希望从阵列中选择非NaN的所有条目:

>>>
>>> x = np.array([[1., 2.], [np.nan, 3.], [np.nan, np.nan]])
>>> x[~np.isnan(x)]
array([ 1.,  2.,  3.])

或者希望为所有负面元素添加常量:

>>>
>>> x = np.array([1., -1., -2., 3])
>>> x[x < 0] += 20
>>> x
array([  1.,  19.,  18.,   3.])


通常,如果索引包括布尔数组,则结果将与插入obj.nonzero()相同位置并使用上述整数数组索引机制相同。 相当于 。x[ind_1, boolean_array, ind_2]x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]

如果只有一个布尔数组且没有整数索引数组,则这是直截了当的。必须注意确保布尔索引具有与其应该使用的维度完全相同的维度。


从数组中,选择总和小于或等于2的所有行:

>>>
>>> x = np.array([[0, 1], [1, 1], [2, 2]])
>>> rowsum = x.sum(-1)
>>> x[rowsum <= 2, :]
array([[0, 1],
       [1, 1]])


但如果rowsum还有两个维度:

>>>
>>> rowsum = x.sum(-1, keepdims=True)
>>> rowsum.shape
(3, 1)
>>> x[rowsum <= 2, :]    # fails
IndexError: too many indices
>>> x[rowsum <= 2]
array([0, 1])


由于额外的维度,最后一个只给出了第一个元素。比较rowsum.nonzero()以了解此示例。

通过obj.nonzero()类比可以最好地理解组合多个布尔索引数组或布尔与整数索引数组 。该函数ix_ 还支持布尔数组,并且可以毫无意外地工作。


使用布尔索引选择加起来为偶数的所有行。同时,应使用高级整数索引选择列0和2。使用该ix_功能可以通过以下方式完成:

>>>
>>> x = array([[ 0,  1,  2],
...            [ 3,  4,  5],
...            [ 6,  7,  8],
...            [ 9, 10, 11]])
>>> rows = (x.sum(-1) % 2) == 0
>>> rows
array([False,  True, False,  True])
>>> columns = [0, 2]
>>> x[np.ix_(rows, columns)]
array([[ 3,  5],
       [ 9, 11]])


没有np.ix_呼叫或只选择对角线元素。

或者没有np.ix_(比较整数数组示例):

>>>
>>> rows = rows.nonzero()[0]
>>> x[rows[:, np.newaxis], columns]
array([[ 3,  5],
       [ 9, 11]])


详细说明


这些是一些详细的注释,对于日常索引(无特定顺序)并不重要:

本机NumPy索引类型intp可能与默认的整数数组类型不同。intp是足以安全索引任何数组的最小数据类型; 对于高级索引,它可能比其他类型更快。

对于高级分配,通常不保证迭代顺序。这意味着如果元素设置不止一次,则无法预测最终结果。

空(元组)索引是零维数组的完整标量索引。 如果是零维则x[()]返回标量,否则返回x视图。另一方面,x[...]总是返回一个视图。

如果索引中存在零维数组并且它是完整的整数索引,则结果将是标量而不是零维数组。(不会触发高级索引。)

当存在省略号(...)但没有大小(即替换为零 :)时,结果仍将始终为数组。如果没有高级索引,则为视图,否则为副本。

nonzero布尔数组的等价性不适用于零维布尔数组。

当高级索引操作的结果没有元素但单个索引超出范围时,是否IndexError引发了未定义(例如,超出范围)。x[[], [123]]123

当在赋值期间发生转换错误时(例如,使用字符串序列更新数值数组),被分配的数组可能最终处于不可预测的部分更新状态。但是,如果发生任何其他错误(例如超出范围索引),则阵列将保持不变。

高级索引结果的内存布局针对每个索引操作进行了优化,并且不能假设特定的内存顺序。

当使用一个子类(尤其是其操纵它的形状),默认ndarray.__setitem__行为会调用__getitem__的 基本索引而不是先进的索引。对于这样的子类,最好ndarray.__setitem__使用基类 ndarray视图调用数据。如果子类不返回视图,则必须执行此操作__getitem__。

现场访问

也可以看看

数据类型对象(dtype),标量

如果ndarray对象是结构化数组 ,则可以通过使用字符串索引数组来访问数组的字段,类似于字典。

索引x['field-name']返回数组的新视图,该视图与x具有相同的形状(当字段是子数组时除外)但是数据类型x.dtype['field-name']并且仅包含指定字段中的部分数据。还 记录阵列标量可以被“索引”这种方式。

索引到结构化数组也可以使用字段名称列表来完成, 例如 x[['field-name1','field-name2']]。从NumPy 1.16开始,这将返回仅包含这些字段的视图。在旧版本的numpy中它返回了一个副本。有关多字段索引的详细信息,请参阅结构化阵列的用户指南部分。

如果访问的字段是子数组,则子数组的尺寸将附加到结果的形状。

>>>
>>> x = np.zeros((2,2), dtype=[('a', np.int32), ('b', np.float64, (3,3))])
>>> x['a'].shape
(2, 2)
>>> x['a'].dtype
dtype('int32')
>>> x['b'].shape
(2, 2, 3, 3)
>>> x['b'].dtype
dtype('float64')


Flat Iterator索引


x.flat返回一个迭代器,它将遍历整个数组(以C-contiguous样式,最后一个索引变化最快)。只要选择对象不是元组,也可以使用基本切片或高级索引对此迭代器对象建立索引。这应该从x.flat一维视图的事实中清楚。它可以用于具有1维C风格平面索引的整数索引。因此,任何返回数组的形状都是整数索引对象的形状。

相关文章
|
6月前
|
索引 Python
|
6月前
|
机器学习/深度学习 数据可视化 API
Python Numpy 切片和索引(高级索引、布尔索引、花式索引)
Python Numpy 切片和索引(高级索引、布尔索引、花式索引)
66 3
|
7月前
|
索引 Python
NumPy 教程 之 NumPy 切片和索引 7
NumPy 切片和索引用于访问和修改 `ndarray` 对象。类似于 Python 的列表切片, 使用索引 `[0-n]` 和切片 `slice(start, stop, step)` 或简写为 `[start:stop:step]` 来提取元素。单个索引 `[n]` 获取单个元素, `[n:]` 获取从 `n` 开始的所有元素, `[n:m]` 获取 `n` 至 `m-1` 的元素。省略号 `...` 保持选择维度与数组一致, 如 `a[...,1]` 获取所有第二列, `a[1,...]` 获取第二行, `a[...,1:]` 获取所有第二列及之后的元素。
41 4
|
7月前
|
索引 Python
NumPy 教程 之 NumPy 高级索引 3
NumPy高级索引包括整数数组索引、布尔索引及花式索引,能访问并操作数组中的任意元素。例如,使用整数数组索引可以从多维数组中选取特定位置的元素。对于一个4x3数组`x`,通过定义行索引`rows`和列索引`cols`为`[[0,0],[3,3]]`和`[[0,2],[0,2]]`,可以获取四个角的元素:`x[rows,cols]`,结果为`[[0 2] [9 11]]`。此外,结合切片与索引数组可进一步定制数据选择,如`a[1:3, 1:3]`或`a[...,1:]`等。
38 3
|
6月前
|
索引 Python
NumPy 教程 之 NumPy 高级索引 6
NumPy高级索引包括 using 整数数组、布尔数组等来 access 数组元素, enabling 复杂的操作和 modifications. **布尔索引** uses 布尔数组 to index 目标数组, filtering 元素 based on 条件.
30 2
|
6月前
|
索引 Python
NumPy 教程 之 NumPy 高级索引 9
NumPy高级索引包括整数数组索引、布尔索引及花式索引,能实现对数组元素的灵活访问与复杂操作。其中,花式索引通过整数数组指定目标轴的下标来选取元素,不同于切片,它总是返回新数组。例如,对二维数组使用倒序索引数组时,会得到指定行的新数组:[[16 17 18 19], [24 25 26 27], [28 29 30 31], [4 5 6 7]]。
50 1
|
6月前
|
索引 Python
NumPy 教程 之 NumPy 高级索引 10
NumPy的高级索引功能强大,支持整数数组索引、布尔索引等多种方式,能够灵活访问和操作数组中的元素。花式索引通过整数数组选取特定位置的数据,不同于切片,它总是创建新数组。使用`np.ix_`处理多维索引时,可实现笛卡尔积效果,选取特定行与列的组合,如示例中从一个二维数组精确取出指定位置的子矩阵。
49 0
|
5月前
|
机器学习/深度学习 数据处理 Python
从NumPy到Pandas:轻松转换Python数值库与数据处理利器
从NumPy到Pandas:轻松转换Python数值库与数据处理利器
141 1
|
6月前
|
机器学习/深度学习 数据处理 计算机视觉
NumPy实践宝典:Python高手教你如何轻松玩转数据处理!
【8月更文挑战第22天】NumPy是Python科学计算的核心库,专长于大型数组与矩阵运算,并提供了丰富的数学函数。首先需安装NumPy (`pip install numpy`)。之后可通过创建数组、索引与切片、执行数学与逻辑运算、变换数组形状及类型、计算统计量和进行矩阵运算等操作来实践学习。NumPy的应用范围广泛,从基础的数据处理到图像处理都能胜任,是数据科学领域的必备工具。
75 0
|
3月前
|
存储 数据处理 Python
Python科学计算:NumPy与SciPy的高效数据处理与分析
【10月更文挑战第27天】在科学计算和数据分析领域,Python凭借简洁的语法和强大的库支持广受欢迎。NumPy和SciPy作为Python科学计算的两大基石,提供了高效的数据处理和分析工具。NumPy的核心功能是N维数组对象(ndarray),支持高效的大型数据集操作;SciPy则在此基础上提供了线性代数、信号处理、优化和统计分析等多种科学计算工具。结合使用NumPy和SciPy,可以显著提升数据处理和分析的效率,使Python成为科学计算和数据分析的首选语言。
110 3