https://docs.scipy.org/doc/nu...html
ndarrays可使用标准Python x[obj]
语法对其进行索引 ,其中x
是数组,obj
是选择方式。有三种可用的索引:字段访问,基本切片,高级索引。到底是哪个取决于obj
。python
注意
在Python中,x[(exp1, exp2, ..., expN)]
至关于x[exp1, exp2, ..., expN];
后者只是前者的语法糖。
基本切片将 Python 的切片基本概念扩展到 N 维。当obj
是一个slice对象(由括号内的start:stop:step
符号构造)、整数或切片对象和整数的元组时,会发生基本切片。也包括省略号(三个点)和newaxis对象。数组
从版本1.15.0开始不推荐使用:为了保持向后兼容Numeric
中的常见用法,若是选择对象是包含 slice 对象、省略号,或 newaxis 对象的任何非 nararray 和非元组序列(例如 list),则也会启动基本切片,但不适用于整数数组或其余嵌入序列。安全
使用 N 个整数进行索引的最简单状况返回表示相应项的数组标量。正如在 Python 中,全部下标是从零开始:对我个索引你,取值范围为 $$ 0 \le n_i < d_i $$ 其中d_i是 个人阵列的形状的个元素。负指数被解释为从数组的末尾开始计数(即,若是 n_i <0,则意味着n_i + d_i)。函数
基本切片生成的全部数组始终 是原始数组的视图。布局
序列切片的标准规则适用于基于每维的基本切片(包括使用步骤索引)。要记住的一些有用的概念包括:优化
基本切片语法是i:j:k其中我是起始索引, j是中止索引,而且ķ是步骤 $$ k \neq 0 $$ 。这将选择米元件(在对应的尺寸)与索引值我,i,i+k,...,1 +(m - 1)k, 其中 $$ m = q +(r \ neq0)$$和 q 和 r 是经过j-i 除 k 所得到的商和余数: $$ j - i = qk + r $$,所以 $$ i +(m - 1)k <j $$。code
例htm
>>> >>> x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> x[1:7:2] array([1, 3, 5])
负i和j被解释为n + i和n + j,其中 n是相应维度中的元素数量。负k使得踩踏指向更小的指数。对象
例
>>> >>> x[-2:10] array([8, 9]) >>> x[-3:3:-1] array([7, 6, 5, 4])
假设n是要切片的维度中的元素数。而后,若是我没有给出其默认值为0 K> 0和 N - 1为ķ<0 。若是没有给出j,则对于k> 0 ,默认为n ; 对于k <0,默认为-n-1。若是没有给出k,则默认为1.注意, 与此相同,表示沿此轴选择全部索引。:::
例
>>> >>> x[5:] array([5, 6, 7, 8, 9])
若是选择元组中的对象数小于 N,则:假定任何后续维。
例
>>> >>> x = np.array([[[1],[2],[3]], [[4],[5],[6]]]) >>> x.shape (2, 3, 1) >>> x[1:2] array([[[4], [5], [6]]])
Ellipsis扩展为:制做与长度相同的选择元组所需的对象数x.ndim。可能只存在一个省略号。
例
>>> >>> x[...,0] array([[1, 2, 3], [4, 5, 6]])
newaxis选择元组中的每一个对象用于将所得选择的维度扩展一个单位长度维度。添加的维度是newaxis 对象在选择元组中的位置。
例
>>> >>> x[:,np.newaxis,:,:].shape (2, 1, 3, 1)
整数i返回相同的值,i:i+1 除了返回的对象的维度减小1.特别是,具备第p个元素的整数(和全部其余条目:)的选择元组返回具备维度的相应子数组N - 1。若是N = 1, 则返回的对象是数组标量。Scalars中解释了这些对象。
若是选择元组具备:除做为切片对象的第p个条目以外的 全部条目i:j:k,则返回的数组具备经过链接由元素i,i + k,...,i +的整数索引返回的子数组造成的维N. m - 1)k <j,
:切片元组中具备多个非条目的基本切片,就像使用单个非:条目重复应用切片同样,其中:连续地获取非条目(全部其余非:条目被替换:)。所以, 在基本切片下的x[ind1,...,ind2,:]行为xind1。
警告
对于高级索引,上述状况并不是如此。
您可使用切片来设置数组中的值,可是(与列表不一样)您永远不会增加数组。要设置的值的大小 必须(可广播)为与其相同的形状 。x[obj] = valuex[obj]
注意
请记住,切片元组老是能够构造为obj 并在x[obj]符号中使用。能够在构造中使用切片对象来代替[start:stop:step] 符号。例如,x[1:10:5,::-1]也能够实现为。这对于构造适用于任意维数组的通用代码很是有用。obj = (slice(1,10,5), slice(None,None,-1)); x[obj]
numpy.newaxis
该newaxis对象可用于全部切片操做,以建立长度为1的轴。newaxis是'None'的别名,'None'能够用来代替相同的结果。
当选择对象obj是非元组序列对象,ndarray(数据类型为整数或bool)或具备至少一个序列对象或ndarray(数据类型为integer或bool)的元组时,将触发高级索引。高级索引有两种类型:整数和布尔值。
高级索引始终返回数据的副本(与返回视图的基本切片造成对比)。
警告
高级索引的定义意味着x[(1,2,3),]根本不一样于x[(1,2,3)]。后者至关于x[1,2,3]触发基本选择,而前者将触发高级索引。必定要明白为何会这样。
同时认识到x[[1,2,3]]将触发高级索引,而因为上面提到的不推荐的数字兼容性, x[[1,2,slice(None)]]将触发基本切片。
整数数组索引容许根据数组的N维索引选择数组中的任意项。每一个整数数组表示该维度的许多索引。
当索引包含尽量多的整数数组时,索引的数组具备维度,索引是直接的,但与切片不一样。
高级索引始终做为一个广播和迭代:
result[i_1, ..., i_M] == x[ind_1[i_1, ..., i_M], ind_2[i_1, ..., i_M], ..., ind_N[i_1, ..., i_M]]
请注意,结果形状与(广播)索引数组形状相同。ind_1, ..., ind_N
例
从每一行开始,应选择一个特定元素。行索引是just ,列索引指定要为相应行选择的元素。将二者结合使用可使用高级索引解决任务:0, 1, 2
>>> >>> x = np.array([[1, 2], [3, 4], [5, 6]]) >>> x[[0, 1, 2], [0, 1, 0]] array([1, 4, 5])
为了实现相似于上面的基本切片的行为,可使用广播。该功能ix_能够帮助这种广播。经过示例能够最好地理解这一点。
例
从4x3阵列中,应使用高级索引选择角元素。所以,列是其中之一的全部元素和行是须要选择的行。要使用高级索引,须要明确选择全部元素。使用前面解释的方法能够写:0, 2
>>> >>> x = array([[ 0, 1, 2], ... [ 3, 4, 5], ... [ 6, 7, 8], ... [ 9, 10, 11]]) >>> rows = np.array([[0, 0], ... [3, 3]], dtype=np.intp) >>> columns = np.array([[0, 2], ... [0, 2]], dtype=np.intp) >>> x[rows, columns] array([[ 0, 2], [ 9, 11]])
可是,因为上面的索引数组只是重复自身,所以可使用广播(比较诸如此类的操做 )来简化:rows[:, np.newaxis] + columns
>>> >>> rows = np.array([0, 3], dtype=np.intp) >>> columns = np.array([0, 2], dtype=np.intp) >>> rows[:, np.newaxis] array([[0], [3]]) >>> x[rows[:, np.newaxis], columns] array([[ 0, 2], [ 9, 11]])
这种广播也可使用如下功能实现ix_:
>>> >>> x[np.ix_(rows, columns)] array([[ 0, 2], [ 9, 11]])
请注意,若是没有np.ix_调用,只会选择对角线元素,如上例所示。对于使用多个高级索引进行索引,这个差别是最重要的。
结合高级索引和基本索引
当至少有一个slice(:),省略号(...)或newaxis 索引(或者数组的维度多于高级索引)时,行为可能会更复杂。这就像链接每一个高级索引元素的索引结果同样
在最简单的状况下,只有一个单一的指标先进。单个高级索引能够例如替换切片,而且结果数组将是相同的,可是,它是副本而且能够具备不一样的存储器布局。当可能时,切片是优选的。
例
>>> >>> 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')
x.flat返回一个迭代器,它将遍历整个数组(以C-contiguous样式,最后一个索引变化最快)。只要选择对象不是元组,也可使用基本切片或高级索引对此迭代器对象创建索引。这应该从x.flat一维视图的事实中清楚。它能够用于具备1维C风格平面索引的整数索引。所以,任何返回数组的形状都是整数索引对象的形状。