05.Numpy切片索引

基本索引

ndarray对象的内容可以通过索引或切片来访问和修改,就像 Python 的内置容器对象一样。

如前所述,ndarray对象中的元素遵循基于零的索引。 有三种可用的索引方法类型: 字段访问,基本切片高级索引

基本切片是 Python 中基本切片概念到 n 维的扩展。 通过将startstopstep参数提供给内置的slice函数来构造一个 Python slice对象。 此slice对象被传递给数组来提取数组的一部分。

示例

>>> np.arange(10)[slice(2, 7, 2)]
array([2, 4, 6])
>>> np.arange(10)[0]
0
>>> np.arange(10)[:]
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(10)[2:7]
array([2, 3, 4, 5, 6])
>>> a = np.array([[1,2,3],[3,4,5],[4,5,6]])
>>> a[1]
array([3, 4, 5])
>>> a[2, ...]
array([4, 5, 6])  
  • 在上面的例子中,ndarray对象由arange()函数创建。 然后,分别用起始,终止和步长值272定义切片对象。 当这个切片对象传递给ndarray时,会对它的一部分进行切片,从索引27,步长为2

  • 通过将由冒号分隔的切片参数(start:stop:step)直接提供给ndarray对象,也可以获得相同的结果。

  • 如果只输入一个参数,则将返回与索引对应的单个项目。 如果使用a[:],则从该索引向后的所有项目将被提取。 如果使用两个参数(以:分隔),则对两个索引之间的元素以默认步骤进行切片。

  • 上面的描述也可用于多维ndarray

  • 切片还可以包括省略号(...),来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号,它将返回包含行中元素的ndarray

高级索引

如果一个ndarray是非元组序列,数据类型为整数或布尔值的ndarray,或者至少一个元素为序列对象的元组,我们就能够用它来索引ndarray。高级索引始终返回数据的副本。 与此相反,切片只提供了一个视图。

有两种类型的高级索引:整数和布尔值。

整数索引

这种机制有助于基于 N维索引来获取数组中任意元素。 每个整数数组表示该维度的下标值。 当索引的元素个数就是目标ndarray的维度时,会变得相当直接。

以下示例获取了ndarray对象中每一行指定列的一个元素。 因此,行索引包含所有行号,列索引指定要选择的元素。

示例 1

>>> np.array([[1,  2],  [3,  4],  [5,  6]])[[0, 1, 2], [0, 1, 0]]
array([1, 4, 5])            

该结果包括数组中(0,0)(1,1)(2,0)位置处的元素。

下面的示例获取了 4X3 数组中的每个角处的元素。 行索引是[0,0][3,3],而列索引是[0,2][0,2]

示例 2

>>> x
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
>>> row = np.array([[0, 0], [3, 3]])
>>> col = np.array([[0, 2], [0, 2]])
>>> x[row, col]
array([[ 0,  2],
       [ 9, 11]])                                         

返回的结果是包含每个角元素的ndarray对象。

高级和基本索引可以通过使用切片:或省略号...与索引数组组合。 以下示例使用slice作为列索引和高级索引。 当切片用于两者时,结果是相同的。 但高级索引会导致复制,并且可能有不同的内存布局。

示例 3

>>> x = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
>>> x
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
>>> x[1:4, 1:3]
array([[ 4,  5],
       [ 7,  8],
       [10, 11]])
>>> x[1:4, [1, 2]]
array([[ 4,  5],
       [ 7,  8],
       [10, 11]])

布尔索引

当结果对象是布尔运算(例如比较运算符)的结果时,将使用此类型的高级索引。

示例 1

这个例子中,大于 5 的元素会作为布尔索引的结果返回。

>>> x = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
>>> x[x>5]
array([ 6,  7,  8,  9, 10, 11])

示例 2

这个例子使用了~(取补运算符)来过滤NaN

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

示例 3

以下示例显示如何从数组中过滤掉非复数元素。

>>> a = np.array([1,2+6j,5,3.5+5j])
>>> a[np.iscomplex(a)]
array([2. +6.j, 3.5+5.j])

多维数组

多维数组的存取和一维数组类似,因为多维数组有多个轴,因此它的下标需要用多个值来表示,NumPy采用组元(tuple)作为数组的下标。组元不需要圆括号,虽然经常在Python中用圆括号将组元括起来,但是其实组元的语法定义只需要用逗号隔开即可,例如 x,y=y,x 就是用组元交换变量值的一个例子。

使用数组切片语法访问多维数组中的元素

如何创建这个数组

你也许会对如何创建a这样的数组感到好奇,数组a实际上是一个加法表,纵轴的值为0, 10, 20, 30, 40, 50;横轴的值为0, 1, 2, 3, 4, 5。纵轴的每个元素都和横轴的每个元素求和,就得到图中所示的数组a。你可以用下面的语句创建它,至于其原理我们将在后面的章节进行讨论:

>>> np.arange(0, 60, 10).reshape(-1, 1) + np.arange(0, 6)
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])

多维数组同样也可以使用整数序列和布尔数组进行存取。

使用整数序列和布尔数组访问多维数组中的元素

a[(0,1,2,3,4),(1,2,3,4,5)] : 用于存取数组的下标和仍然是一个有两个元素的组元,组元中的每个元素都是整数序列,分别对应数组的第0轴和第1轴。从两个序列的对应位置取出两个整数组成下标: a[0,1], a[1,2], ..., a[4,5]。

a[3:, [0, 2, 5]] : 下标中的第0轴是一个范围,它选取第3行之后的所有行;第1轴是整数序列,它选取第0, 2, 5三列。

a[mask, 2] : 下标的第0轴是一个布尔数组,它选取第0,2,5行;第1轴是一个整数,选取第2列。

where

使用 where 函数能将索引掩码转换成索引位置:

>>> np.where([[True, False], [True, True]],
...          [[1, 2], [3, 4]],
...          [[9, 8], [7, 6]])
array([[1, 8],
       [3, 4]])

>>> np.where([[0, 1], [1, 0]])
(array([0, 1]), array([1, 0]))

>>> x = np.arange(9.).reshape(3, 3)
>>> np.where( x > 5 )
(array([2, 2, 2]), array([0, 1, 2]))
>>> x[np.where( x > 3.0 )]               # Note: result is 1D.
array([ 4.,  5.,  6.,  7.,  8.])
>>> np.where(x < 5, x, -1)               # Note: broadcasting.
array([[ 0.,  1.,  2.],
       [ 3.,  4., -1.],
       [-1., -1., -1.]])

>>> # Find the indices of elements of `x` that are in `goodvalues`.
>>> goodvalues = [3, 4, 7]
>>> ix = np.isin(x, goodvalues)
>>> ix
array([[False, False, False],
       [ True,  True, False],
       [False,  True, False]])
>>> np.where(ix)
(array([1, 1, 2]), array([0, 1, 1]))

take

take 函数与高级索引(fancy indexing)用法相似:

>>> a = [4, 3, 5, 7, 6, 8]
>>> indices = [0, 1, 4]
>>> np.take(a, indices)
array([4, 3, 6])

>>> # In this example if `a` is an ndarray, "fancy" indexing can be used.
>>> a = np.array(a)
>>> a[indices]
array([4, 3, 6])

>>> # If `indices` is not one dimensional, the output also has these dimensions.
>>> np.take(a, [[0, 1], [2, 3]])
array([[4, 3],
       [5, 7]])

但是 take 也可以用在 list 和其它对象上:

choose

选取多个数组的部分组成新的数组:

>>> choices = [[0, 1, 2, 3], [10, 11, 12, 13],
...   [20, 21, 22, 23], [30, 31, 32, 33]]
>>> np.choose([2, 3, 1, 0], choices
... # the first element of the result will be the first element of the
... # third (2+1) "array" in choices, namely, 20; the second element
... # will be the second element of the fourth (3+1) choice array, i.e.,
... # 31, etc.
... )
array([20, 31, 12,  3])
>>> np.choose([2, 4, 1, 0], choices, mode='clip') # 4 goes to 3 (4-1)
array([20, 31, 12,  3])
>>> # because there are 4 choice arrays
>>> np.choose([2, 4, 1, 0], choices, mode='wrap') # 4 goes to (4 mod 4)
array([20,  1, 12,  3])
>>> # i.e., 0
>>> # A couple examples illustrating how choose broadcasts:
>>> a = [[1, 0, 1], [0, 1, 0], [1, 0, 1]]
>>> choices = [-10, 10]
>>> np.choose(a, choices)
array([[ 10, -10,  10],

猜你喜欢

转载自www.cnblogs.com/oneTOinf/p/10480433.html