Numpy 使用教程--Numpy 数组索引及其他用法
一、实验介绍
1.1 实验内容
如果你使用 Python 语言进行科学计算,那么一定会接触到 Numpy。Numpy 是支持 Python 语言的数值计算扩充库,其拥有强大的高维度数组处理与矩阵运算能力。除此之外,Numpy 还内建了大量的函数,方便你快速构建数学模型。
1.2 实验知识点
- Numpy 数组索引
- Numpy 其他用法
1.3 实验环境
- python2.7
- Xfce 终端
- ipython 终端
1.4 适合人群
本课程难度为一般,属于初级级别课程,适合具有 Python 基础,并对使用 Numpy 进行科学计算感兴趣的用户。
二、Numpy 数组索引和切片
我们已经明确了,Ndarray 是 Numpy 的组成核心,那么对于 Numpy 的多维数组,其实它完整集成了 python 对于数组的索引语法 array[obj]。随着 obj 的不同,我们可以实现字段访问、数组切片、以及其他高级索引功能。
2.1 数组索引
我们可以通过索引值(从 0 开始)来访问 Ndarray 中的特定位置元素。Numpy 中的索引和 python 对 list 索引的方式非常相似,但又有所不同。我们一起来看一下:
首先是,一维数据索引:
>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 获取索引值为 1 的数据
>>> a[1]
1
# 分别获取索引值为 1,2,3 的数据
>>> a[[1, 2, 3]]
array([1, 2, 3])
对于二维数据而言:
>>> import numpy as np
>>> a = np.arange(20).reshape(4,5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
# 获取第 2 行,第 3 列的数据
>>> a[1,2]
7
如果,我们使用 python 中的 list 索引同样的值,看看有什么区别:
# 创建一个数据相同的 list
>>> a = [[ 0, 1, 2, 3, 4],[ 5, 6, 7, 8, 9],[10, 11, 12, 13, 14],[15, 16, 17, 18, 19]]
# 按照上面的方法获取第 2 行,第 3 列的数据,报错。
>>> a[1,2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not tuple
# python 中 list 索引 2 维数据的方法
>>> a[1][2]
7
如何索引二维 Ndarray 中的多个元素值,这里使用逗号,
分割:
>>> import numpy as np
>>> a = np.arange(20).reshape(4,5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
# 索引
>>> a[[1,2],[3,4]]
array([ 8, 14])
这里需要注意索引的对应关系。我们实际获取的是[1,3]
,也就是第2
行和第4
列对于的值8
。以及[2, 4]
,也就是第3
行和第5
列对于的值14
。
那么,三维数据呢?
>>> import numpy as np
>>> a = np.arange(30).reshape(2,5,3)
>>> a
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]],
[[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]])
# 索引
>>> a[[0,1],[1,2],[1,2]]
array([ 4, 23])
这里,[0,1]
分布代表 axis = 0
和 axis = 1
。而,后面的[1,2],[1,2]
分别选择了第2
行第2
列和第 3
行第3
列的两个数。
2.2 数组切片
Numpy 里面针对Ndarray
的数组切片和 python 里的list
切片操作是一样的。其语法为:
Ndarray[start:stop:step]
start:stop:step
分布代表起始索引:截至索引:步长
。对于一维数组:
>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[:5]
array([0, 1, 2, 3, 4])
>>> a[5:10]
array([5, 6, 7, 8, 9])
>>> a[0:10:2]
array([0, 2, 4, 6, 8])
对于多维数组,我们只需要用逗号,
分割不同维度即可:
>>> import numpy as np
>>> a = np.arange(20).reshape(4,5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
# 先取第 3,4 列(第一个维度),再取第 1,2,3 行(第二个维度)。
>>> a[0:3,2:4]
array([[ 2, 3],
[ 7, 8],
[12, 13]])
# 按步长为 2 取所有列和所有行的数据。
>>> a[:,::2]
array([[ 0, 2, 4],
[ 5, 7, 9],
[10, 12, 14],
[15, 17, 19]])
当超过 3 维或更多维时,用 2 维数据的切片方式类推即可。
2.3 索引与切片区别
你可能有点疑问,上面的索引和切片怎么看起来这么相似呢?
它们的语法的确很相似,但实际上有区别:
1. 修改切片中的内容会影响原始数组。
>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[1] = 100
>>> a
array([0, 100, 2, 3, 4, 5, 6, 7, 8, 9])
除此之外,切片只能通过步长控制得到连续的值,而索引可以得到任意值。也就是说,索引的*度更大。
三、排序、搜索、计数
最后,再介绍几个 numpy 针对数组元素的使用方法,分别是排序、搜索和计数。
3.1 排序
我们可以使用 numpy.sort
方法对多维数组元素进行排序。其方法为:
numpy.sort(a, axis=-1, kind='quicksort', order=None)
其中:
-
a
:数组。 -
axis
:要排序的轴。如果为None
,则在排序之前将数组铺平。默认值为-1
,沿最后一个轴排序。 -
kind
:{'quicksort','mergesort','heapsort'}
,排序算法。默认值为quicksort
。
举个例子:
>>> import numpy as np
>>> a = np.random.rand(20).reshape(4,5)
>>> a
array([[ 0.32930243, 0.63665893, 0.67589989, 0.05413352, 0.26090526],
[ 0.6996066 , 0.66006238, 0.88240934, 0.17563549, 0.03015105],
[ 0.79075184, 0.40115859, 0.39336513, 0.64691791, 0.96333534],
[ 0.20052738, 0.46157057, 0.48653336, 0.34537645, 0.54597273]])
>>> np.sort(a)
array([[ 0.05413352, 0.26090526, 0.32930243, 0.63665893, 0.67589989],
[ 0.03015105, 0.17563549, 0.66006238, 0.6996066 , 0.88240934],
[ 0.39336513, 0.40115859, 0.64691791, 0.79075184, 0.96333534],
[ 0.20052738, 0.34537645, 0.46157057, 0.48653336, 0.54597273]])
除了 numpy.sort,还有这样一些对数组进行排序的方法:
-
numpy.lexsort(keys ,axis)
:使用多个键进行间接排序。 -
numpy.argsort(a ,axis,kind,order)
:沿给定轴执行间接排序。 -
numpy.msort(a)
:沿第 1 个轴排序。 -
numpy.sort_complex(a)
:针对复数排序。
3.2 搜索和计数
除了排序,我们可以通过下面这些方法对数组中元素进行搜索和计数。列举如下:
-
argmax(a ,axis,out)
:返回数组中指定轴的最大值的索引。 -
nanargmax(a ,axis)
:返回数组中指定轴的最大值的索引,忽略 NaN。 -
argmin(a ,axis,out)
:返回数组中指定轴的最小值的索引。 -
nanargmin(a ,axis)
:返回数组中指定轴的最小值的索引,忽略 NaN。 -
argwhere(a)
:返回数组中非 0 元素的索引,按元素分组。 -
nonzero(a)
:返回数组中非 0 元素的索引。 -
flatnonzero(a)
:返回数组中非 0 元素的索引,并铺平。 -
where(条件,x,y)
:根据指定条件,从指定行、列返回元素。 -
searchsorted(a,v ,side,sorter)
:查找要插入元素以维持顺序的索引。 -
extract(condition,arr)
:返回满足某些条件的数组的元素。 -
count_nonzero(a)
:计算数组中非 0 元素的数量。
选取其中的一些方法举例:
>>> import numpy as np
>>> a = np.random.randint(0,10,20)
>>> a
array([3, 2, 0, 4, 3, 1, 5, 8, 4, 6, 4, 5, 4, 2, 6, 6, 4, 9, 8, 9])
>>> np.argmax(a)
17
>>> np.nanargmax(a)
17
>>> np.argmin(a)
2
>>> np.nanargmin(a)
2
>>> np.argwhere(a)
array([[ 0],[ 1],[ 3],[ 4],[ 5],[ 6],[ 7],[ 8],[ 9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19]], dtype=int64)
>>> np.nonzero(a)
(array([ 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], dtype=int64),)
>>> np.flatnonzero(a)
array([ 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], dtype=int64)
>>> np.count_nonzero(a)
19
四、实验总结
最后一章,我们熟悉了 Ndarray 索引与切片相关的方法,这将对灵活处理多维数组提供帮助。除此之外,提到的排序、搜索与计数方法你可能不常用到,但是留下印象,以便不时之需。