NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
NumPy 是一个运行速度非常快的数学库,主要用于数组计算,包含:
- 一个强大的N维数组对象 ndarray
- 广播功能函数
- 整合 C/C++/Fortran 代码的工具
- 线性代数、傅里叶变换、随机数生成等功能
1、数组创建
>>> import numpy as np
>>> arr1 = np.array([1,-1,4,3])
>>> arr1
array([ 1, -1, 4, 3])
#类型指定
>>> arr2 = np.array([1,-1,4,3], dtype='float')
>>> arr2
array([ 1., -1., 4., 3.])
>>> arr2 = np.array([1,-1,4,3], dtype='str')
>>> arr2
#数组嵌套
>>> arr3 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
>>> arr3
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
#范围列表
#numpy.arange(start, stop, step, dtype)
#根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray。
>>> np.arange(0, 10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(0, 10, 0.5)
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. ,
6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5])
#等差数列
#np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
>>> np.linspace(1,10,10)
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
#取值个数改为11
>>> np.linspace(1,10,11)
array([ 1. , 1.9, 2.8, 3.7, 4.6, 5.5, 6.4, 7.3, 8.2, 9.1, 10. ])
#不取最后一个值
>>> np.linspace(1,10,10, endpoint = False)
array([1. , 1.9, 2.8, 3.7, 4.6, 5.5, 6.4, 7.3, 8.2, 9.1])
#log为底的等比数列
#np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
#base 参数意思是取对数的时候 log 的下标。
>>> np.logspace(1,5,base=2,num=10)
array([ 2. , 2.72158 , 3.70349885, 5.0396842 , 6.85795186,
9.33223232, 12.69920842, 17.28095582, 23.51575188, 32. ])
>>> 2 ** np.linspace(1,5,10)
array([ 2. , 2.72158 , 3.70349885, 5.0396842 , 6.85795186,
9.33223232, 12.69920842, 17.28095582, 23.51575188, 32. ])
>>> np.zeros([1,5])
array([[0., 0., 0., 0., 0.]])
>>> np.zeros(6)
array([0., 0., 0., 0., 0., 0.])
>>> np.ones([7,6])
array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
>>> np.eye(6)
array([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 1.]])
>>> np.diag([4,5,8])
array([[4, 0, 0],
[0, 5, 0],
[0, 0, 8]])
>>> np.diag([4,5,8]) +1
array([[5, 1, 1],
[1, 6, 1],
[1, 1, 9]])
2、数组属性
NumPy 数组的维数称为秩(rank),秩就是轴的数量,即数组的维度,一维数组的秩为 1,二维数组的秩为 2,以此类推。
在 NumPy中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。
很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。
NumPy 的数组中比较重要 ndarray 对象属性有:
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray 对象的内存信息 |
ndarray.real | ndarray元素的实部 |
ndarray.imag | ndarray 元素的虚部 |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
#三行四列
>>> arr3.shape
(3, 4)
>>> arr3
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
#维度,2维
>>> arr3.ndim
2
>>> arr1.shape
(4,)
>>> arr1.ndim
1
#查看元素个数
>>> arr3.size
12
>>> arr3.dtype
dtype('int32')
>>> arr3 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]],dtype = 'float')
>>> arr3
array([[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.],
[ 9., 10., 11., 12.]])
>>> arr3.dtype
dtype('float64')
>>>
3、索引和切片
ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。
ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。
>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> s = slice(2,7,2) # 从索引 2 开始到索引 7 停止,间隔为2
>>> a[s]
array([2, 4, 6])
#我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作:
>>> b = a[2:7:2]
>>> b
array([2, 4, 6])
#冒号 : 的解释:如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
>>> b = a[5]
>>> b
5
>>> print(a[2:])
[2 3 4 5 6 7 8 9]
>>> print(a[2:5])
[2 3 4]
#多维数组
>>> a = np.array([[1,2,3],[3,4,5],[4,5,6]])
>>> a
array([[1, 2, 3],
[3, 4, 5],
[4, 5, 6]])
#从数组索引 a[1:] 处开始切割,即取第二,第三个列表
>>> print(a[1:])
[[3 4 5]
[4 5 6]]
#切片还可以包括省略号 …,来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号,它将返回包含行中元素的 ndarray。
>>> print (a[...,1]) # 第2列元素
[2 4 5]
>>> print (a[1,...]) # 第2行元素
[3 4 5]
>>> print (a[...,1:]) # 第2列及剩下的所有元素
[[2 3]
[4 5]
[5 6]]
4、NumPy 高级索引
整数数组索引:
以下实例获取数组中(0,0),(1,1)和(2,0)位置处的元素。
>>> x = np.array([[1, 2], [3, 4], [5, 6]])
>>> x
array([[1, 2],
[3, 4],
[5, 6]])
>>> y = x[[0,1,2], [0,1,0]]
#[0,1,2]代表第一行,第二行,第三行;[0,1,0]代表第一列,第二列,第一列
对应坐标即(0,0),(1,1),(2,0)
>>> y
array([1, 4, 5])
#以下实例获取了 4X3 数组中的四个角的元素。 行索引是 [0,0] 和 [3,3],而列索引是 [0,2] 和 [0,2]。
>>> x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
#我们的数组是:
>>> print (x)
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
>>> rows = np.array([[0,0],[3,3]]) #可以理解成[0,0,3,3]
>>> cols = np.array([[0,2],[0,2]]) #可以理解成[0,2,0,2]
>>> y = x[rows,cols]
>>> print ('这个数组的四个角元素是:')
这个数组的四个角元素是:
>>> print (y)
[[ 0 2]
[ 9 11]]
#相比上种,值汇总在一起
>>> x[[0,0,3,3],[0,2,0,2]]
array([ 0, 2, 9, 11])
#可以借助切片 : 或 … 与索引数组组合。如下面例子:
>>> a = np.array([[1,2,3], [4,5,6],[7,8,9]])
>>> b = a[1:3, 1:3]
>>> c = a[1:3,[1,2]]
>>> d = a[...,1:]
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> b
array([[5, 6],
[8, 9]])
>>> c
array([[5, 6],
[8, 9]])
>>> d
array([[2, 3],
[5, 6],
[8, 9]])
布尔索引:
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
>>> import numpy as np
#以下实例获取大于 5 的元素:
>>> x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
>>> print (x)
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
#大于 5 的元素是:
>>> print (x[x > 5])
[ 6 7 8 9 10 11]
#以下实例使用了 ~(取补运算符)来过滤 NaN。
>>> a = np.array([np.nan, 1,2,np.nan,3,4,5])
>>> print (a[~np.isnan(a)])
[1. 2. 3. 4. 5.]
#以下实例演示如何从数组中过滤掉非复数元素。
>>> a = np.array([1, 2+6j, 5, 3.5+5j])
>>> print (a[np.iscomplex(a)])
[2. +6.j 3.5+5.j]
花式索引:
指的是利用整数数组进行索引。
花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。
花式索引跟切片不一样,它总是将数据复制到新数组中。
#传入顺序索引数组
>>> x=np.arange(32).reshape((8,4))
>>> x
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, 30, 31]])
>>> print (x[[4,2,1,7]]) #角标对应行
[[16 17 18 19]
[ 8 9 10 11]
[ 4 5 6 7]
[28 29 30 31]]
#倒序
>>> print (x[[-4,-2,-1,-7]])
[[16 17 18 19]
[24 25 26 27]
[28 29 30 31]
[ 4 5 6 7]]
#传入多个索引数组
>>> print (x[np.ix_([1,5,7,2],[0,3,1,2])]) #第一个数组用来标识行位置,第二个数组用来标识列位置
[[ 4 7 5 6]
[20 23 21 22]
[28 31 29 30]
[ 8 11 9 10]]
>>> print (x[np.ix_([1,5,7,2],[3,1,2,0])])
[[ 7 5 6 4]
[23 21 22 20]
[31 29 30 28]
[11 9 10 8]]