索引介绍
NumPy的数组对象ndarrays可以和Python标准序列数据类型一样,使用 x[obj] 进行索引操作。其中,x是数组,obj是索引选择。有三种可用的索引:基本切片、高级索引、字段访问。
一、基本切片和索引
Python序列的切片操作是一维的,NumPy 将对数组的切片拓展到了N维。
基本切片语法 i:j:k
:其中i是起始索引,j是停止索引,k是步长。
对于多维数组的索引
array[(x, y, z)]
可以被简写成x[x, y, z]
,这也是NumPy的语法糖。
示例:
>>>x = np.arange(10)
>>>x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
# 简单索引
>>>x[3]
3
# 一维切片
>>>x = np.arange(10)
>>>x[1:7:2]
array([1, 3, 5])
# 多维切片
>>>y = np.arange(20).reshape(4,5)
>>>y
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
>>>y[1:4, 1:4]
array([[ 6, 7, 8],
[11, 12, 13],
[16, 17, 18]])
# i和j为负,则可看作为n+i和n+j,n为维度中元素数量。
# k为负,则步长向前。
>>>x[-2:10]
array([8, 9])
>>>x[-3:3:-1]
array([7, 6, 5, 4])
# 默认写法 ":"
>>>x[4:]
array([4, 5, 6, 7, 8, 9])
# 如果索引元组的元素数小于维度,则假定任何其它维
>>> z = np.array([[[1],[2],[3]], [[4],[5],[6]]])
>>> z.shape
(2, 3, 1)
>>> z[1:2]
array([[[4],
[5]
[6]]])
# 索引中可以使用 "..." 代指其它维度的全部索引,一个索引中只能有一个省略号
>>>z[...,0]
array([[1, 2, 3],
[4, 5, 6]])
# 使用newaxis 增加维度
>>>z[:,np.newaxis,:,:].shape
(2, 1, 3, 1)
注意
- 索引
i
和i:i+1
的区别:
>>>z = np.array([[[1],[2],[3]], [[4],[5],[6]]])
>>>z[0, 0, 0], z[0:1, 0, 0]
(1, array([1]))
- 可以使用切片来设置数组的值,但不能改变数组的形状
- 基本切片只返回数据的视图,并不会返回数据的拷贝
二、高级索引
高级索引有两种类型:整数苏松阴和布尔索引。与基本切片不同,高级索引返回数组的副本。
2.1 整数数组索引
# 整数数组分别表示所需索引的下标。
# 取点[0,0], [1,1], [2,0]
>>>x = np.array([[1, 2], [3, 4], [5, 6]])
>>>x[[0,1,2], [0,1,0]]
array([1, 4, 5])
# 获取了 4X3 数组中的四个角的元素。
# 行索引是 [0,0] 和 [3,3],而列索引是 [0,2] 和 [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]])
# 使用np.ix_(rows, columns)获得相同效果
>>>x[[0,3], [0,2]
注意
如果高级索引和基本切片的结果数组相同,优先使用切片。但是如果需要副本有不同的存储位置,则使用高级索引。
2.2 布尔索引
当索引对象是布尔类型时, 也会发生高级索引。
# 对于array[obj]
# 如果array.ndim == obj.ndim,
# 将返回一个一维数组,其中包含所有obj中为 True 的位置的元素,以row-major为顺序。
>>>x = np.array([[1., 2.], [np.nan, 3.], [np.nan, np.nan]])
>>>np.isnan(x),x[~np.isnan(x)]
(array([[False, False],
[ True, False],
[ True, True]]),
array([1., 2., 3.]))
# 使用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]])
2.3 字段索引
如果数组对象是结构化数组,则可以使用字符串索引来访问数组的字段。使用方式和字典类似。
>>> x = np.zeros((2,2), dtype=[('a', np.int32), ('b', np.float64, (3,3))])
>>>x
array([[(0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]),
(0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])],
[(0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]),
(0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])]],
dtype=[('a', '<i4'), ('b', '<f8', (3, 3))])
>>>x['a']
array([[0, 0],
[0, 0]])
>>>x['a'].dtype
dtype('int32')
>>>x['b']
array([[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]],
[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]])
>>>x['b'].dtype
dtype('float64')