[toc]
NumPy科学计算库
课程介绍
NumPy(Numerical Python)是Python的一种开源的数值计算扩展。提供多维数组对象,各种派生对象(如掩码数组和矩阵),这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库,包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。
第一部分 基本操作
第一节 数组创建
创建数组的最简单的方法就是使用array函数,将Python下的list转换为ndarray。
1 2 3 4 5 6 import numpy as np l = [1 ,3 ,5 ,7 ,9 ] arr = np.array(l) arr
我们可以利用np中的一些内置函数来创建数组,比如我们创建全0的数组,也可以创建全1数组,全是其他数字的数组,或者等差数列数组,正态分布数组,随机数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import numpy as np arr1 = np.ones(10 ) arr2 = np.zeros(10 ) arr3 = np.full(shape = [2 ,3 ],fill_value=2.718 ) arr4 = np.arange(start = 0 ,stop = 20 ,step = 2 ) arr5 = np.linspace(start =0 ,stop = 9 ,num = 10 ) arr6 = np.random.randint(0 ,100 ,size = 10 ) arr7 = np.random.randn(5 ) arr8 = np.random.random(size = 5 )
第二节 查看操作
NumPy的数组类称为ndarray,也被称为别名 array。请注意,numpy.array这与标准Python库类不同array.array,后者仅处理一维数组且功能较少。ndarray对象的重要属性是
1.2.1 数组的轴数、维度
1 2 3 import numpy as np arr = np.random.randint(0 ,100 ,size = (3 ,4 ,5 )) arr.ndim
1.2.2 数组尺寸形状
1 2 3 import numpy as np arr = np.random.randint(0 ,100 ,size = (3 ,4 ,5 )) arr.shape
1.2.3 数组元素的总数
1 2 3 import numpy as np arr = np.random.randint(0 ,100 ,size = (3 ,4 ,5 )) arr.size
1.2.4 数据类型
1 2 3 import numpy as np arr = np.random.randint(0 ,100 ,size = (3 ,4 ,5 )) arr.dtype
1.2.5 数组中每个元素的大小(以字节为单位)
1 2 3 import numpy as np arr = np.random.randint(0 ,100 ,size = (3 ,4 ,5 )) arr.itemsize
第三节 文件IO操作
1.3.1 保存数组
save方法保存ndarray到一个npy文件,也可以使用savez将多个array保存到一个.npz文件中
1 2 3 4 5 6 x = np.random.randn(5 ) y = np.arange(0 ,10 ,1 ) np.save("x_arr" ,x) np.savez("some_array.npz" ,xarr = x,yarr=y)
1.3.2 读取
load方法来读取存储的数组,如果是.npz文件的话,读取之后相当于形成了一个key-value类型的变量,通过保存时定义的key来获取相应的array
1 2 3 4 np.load('x_arr.npy' ) np.load('some_array.npz' )['yarr' ]
1.3.3 读写csv、txt文件
1 2 3 4 5 arr = np.random.randint(0 ,10 ,size = (3 ,4 )) np.savetxt("arr.csv" ,arr,delimiter=',' ) np.loadtxt("arr.csv" ,delimiter=',' ,dtype=np.int32)
第二部分 数据类型
ndarray的数据类型:
int: int8、uint8、int16、int32、int64
float: float16、float32、float64
str
array创建时,指定
1 2 3 import numpy as np np.array([1 ,2 ,5 ,8 ,2 ],dtype = 'float32' )
asarray转换时指定
1 2 3 4 5 import numpy as np arr = [1 ,3 ,5 ,7 ,2 ,9 ,0 ] np.asarray(arr,dtype = 'float32' )
数据类型转换astype
1 2 3 4 5 import numpy as np arr = np.random.randint(0 ,10 ,size = 5 ,dtype = 'int16' ) arr.astype('float32' )
第三部分 数组运算
加减乘除幂运算
1 2 3 4 5 6 7 import numpy as np arr1 = np.array([1 ,2 ,3 ,4 ,5 ]) arr2 = np.array([2 ,3 ,1 ,5 ,9 ]) arr1 - arr2 arr1 * arr2 arr1 / arr2 arr1**arr2
逻辑运算
1 2 3 4 5 6 7 8 import numpy as np arr1 = np.array([1 ,2 ,3 ,4 ,5 ]) arr2 = np.array([1 ,0 ,2 ,3 ,5 ]) arr1 < 5 arr1 >= 5 arr1 == 5 arr1 == arr2 arr1 > arr2
数组与标量计算
数组与标量的算术运算也会将标量值传播到各个元素
1 2 3 4 5 import numpy as np arr = np.arange(1 ,10 )1 /arr arr+5 arr*5
*=、+=、-=操作
某些操作(例如+=和*=)只会修改现有数组,而不是创建一个新数组。
1 2 3 4 5 6 import numpy as np arr1 = np.arange(5 ) arr1 +=5 arr1 -=5 arr1 *=5
第四部分 复制和视图
在操作数组时,有时会将其数据复制到新数组中,有时不复制。
对于初学者来说,这通常会引起混乱。有以下三种情况
完全没有复制
1 2 3 4 5 6 import numpy as np a = np.random.randint(0 ,100 ,size = (4 ,5 )) b = a a is b b[0 ,0 ] = 1024 display(a,b)
查看或浅拷贝
不同的数组对象可以共享相同的数据。该view方法创建一个查看相同数据的新数组对象
1 2 3 4 5 6 7 8 9 import numpy as np a = np.random.randint(0 ,100 ,size = (4 ,5 )) b = a.view() a is b b.base is a b.flags.owndata a.flags.owndata b[0 ,0 ] = 1024 display(a,b)
深拷贝
1 2 3 4 5 6 7 8 9 import numpy as np a = np.random.randint(0 ,100 ,size = (4 ,5 )) b = a.copy() b is a b.base is a b.flags.owndata a.flags.owndata b[0 ,0 ] = 1024 display(a,b)
第五部分 索引、切片和迭代
第一节 基本索引和切片
numpy中数组切片是原始数组的视图,这意味着数据不会被复制,视图上任何数据的修改都会反映到原数组上
1 2 3 4 5 6 7 8 9 10 11 12 arr = np.array([0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ]) arr[5 ] arr[5 :8 ] arr[2 ::2 ] arr[::3 ] arr[1 :7 :2 ] arr[::-1 ] arr[::-2 ] arr[5 :8 ]=12 temp = arr[5 :8 ] temp[1 ] = 1024 arr
对于二维数组或者高维数组,我们可以按照之前的知识来索引,当然也可以传入一个以逗号隔开的索引列表来选区单个或多个元素
1 2 3 4 5 6 7 8 9 arr2d = np.array([[1 ,3 ,5 ],[2 ,4 ,6 ],[-2 ,-7 ,-9 ],[6 ,6 ,6 ]]) arr2d[0 ,-1 ] arr2d[0 ,2 ] arr2d[:2 ,-2 :] arr2d[:2 ,1 :]
第二节 花式索引和索引技巧
整数数组进行索引即花式索引,其和切片不一样,它总是将数据复制到新数组中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import numpy as np arr1 = np.array([1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ]) arr2 = arr1[[1 ,3 ,3 ,5 ,7 ,7 ,7 ]] arr2[-1 ] = 1024 arr2d = np.array([[1 ,3 ,5 ,7 ,9 ],[2 ,4 ,6 ,8 ,10 ],[12 ,18 ,22 ,23 ,37 ],[123 ,55 ,17 ,88 ,103 ]]) arr2d[[1 ,3 ]] arr2d[([1 ,3 ],[2 ,4 ])] arr2d[np.ix_([1 ,3 ,3 ,3 ],[2 ,4 ,4 ])] arr2d[[1 ,3 ,3 ,3 ]][:,[2 ,4 ,4 ]]
1 2 3 4 5 6 7 8 9 names = np.array(['softpo' ,'Brandon' ,'Will' ,'Michael' ,'Will' ,'Ella' ,'Daniel' ,'softpo' ,'Will' ,'Brandon' ]) cond1 = names == 'Will' cond1 names[cond1] arr = np.random.randint(0 ,100 ,size = (10 ,8 )) cond2 = arr > 90 arr[cond2]
第六部分 形状操作
数组变形
1 2 3 4 import numpy as np arr1 = np.random.randint(0 ,10 ,size = (3 ,4 ,5 )) arr2 = arr1.reshape(12 ,5 ) arr3 = arr1.reshape(-1 ,5 )
数组转置
1 2 3 4 5 import numpy as np arr1 = np.random.randint(0 ,10 ,size = (3 ,5 )) arr1.T arr2 = np.random.randint(0 ,10 ,size = (3 ,6 ,4 )) np.transpose(arr2,axes=(2 ,0 ,1 ))
数组堆叠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import numpy as np arr1 = np.array([[1 ,2 ,3 ]]) arr2 = np.array([[4 ,5 ,6 ]]) np.concatenate([arr1,arr2],axis = 0 ) np.concatenate([arr1,arr2],axis = 1 ) np.hstack((arr1,arr2)) np.vstack((arr1,arr2))
split数组拆分
1 2 3 4 5 6 7 import numpy as np arr = np.random.randint(0 ,10 ,size = (6 ,5 )) np.split(arr,indices_or_sections=2 ,axis = 0 ) np.split(arr,indices_or_sections=[2 ,3 ],axis = 1 ) np.vsplit(arr,indices_or_sections=3 ) np.hsplit(arr,indices_or_sections=[1 ,4 ])
第七部分 广播机制
当两个数组的形状并不相同的时候,我们可以通过扩展数组的方法来实现相加、相减、相乘等操作,这种机制叫做广播(broadcasting)
一维数组广播
1 2 3 4 5 import numpy as np arr1 = np.sort(np.array([0 ,1 ,2 ,3 ]*3 )).reshape(4 ,3 ) arr2 = np.array([1 ,2 ,3 ]) arr3 = arr1 + arr2 arr3
二维数组的广播
1 2 3 4 5 import numpy as np arr1 = np.sort(np.array([0 ,1 ,2 ,3 ]*3 )).reshape(4 ,3 ) arr2 = np.array([[1 ],[2 ],[3 ],[4 ]]) arr3 = arr1 + arr2 arr3
三维数组广播
1 2 3 4 5 import numpy as np arr1 = np.array([0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ]*3 ).reshape(3 ,4 ,2 ) arr2 = np.array([0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ]).reshape(4 ,2 ) arr3 = arr1 + arr2 arr3
第八部分 通用函数
第一节 通用函数:元素级数字函数
abs、sqrt、square、exp、log、sin、cos、tan,maxinmum、minimum、all、any、inner、clip、round、trace、ceil、floor
1 2 3 4 5 6 7 8 9 10 11 import numpy as np arr1 = np.array([1 ,4 ,8 ,9 ,16 ,25 ]) np.sqrt(arr1) np.square(arr1) np.clip(arr1,2 ,16 ) x = np.array([1 ,5 ,2 ,9 ,3 ,6 ,8 ]) y = np.array([2 ,4 ,3 ,7 ,1 ,9 ,0 ]) np.maximum(x,y) arr2 = np.random.randint(0 ,10 ,size = (5 ,5 )) np.inner(arr2[0 ],arr2)
第二节 where函数
where 函数,三个参数,条件为真时选择值的数组,条件为假时选择值的数组
1 2 3 4 5 6 7 8 9 import numpy as np arr1 = np.array([1 ,3 ,5 ,7 ,9 ]) arr2 = np.array([2 ,4 ,6 ,8 ,10 ]) cond = np.array([True ,False ,True ,True ,False ]) np.where(cond,arr1,arr2) arr3 = np.random.randint(0 ,30 ,size = 20 ) np.where(arr3 < 15 ,arr3,-15 )
第三节 排序方法
np中还提供了排序方法,排序方法是就地排序,即直接改变原数组
arr.sort()、np.sort()、arr.argsort()
1 2 3 4 5 6 import numpy as np arr = np.array([9 ,3 ,11 ,6 ,17 ,5 ,4 ,15 ,1 ]) arr.sort() np.sort(arr) arr = np.array([9 ,3 ,11 ,6 ,17 ,5 ,4 ,15 ,1 ]) arr.argsort()
第四节 集合运算函数
1 2 3 4 5 A = np.array([2 ,4 ,6 ,8 ]) B = np.array([3 ,4 ,5 ,6 ]) np.intersect1d(A,B) np.union1d(A,B) np.setdiff1d(A,B)
第五节 数学和统计函数
min、max、mean、median、sum、std、var、cumsum、cumprod、argmin、argmax、argwhere、cov、corrcoef
1 2 3 4 5 6 7 8 9 10 11 import numpy as np arr1 = np.array([1 ,7 ,2 ,19 ,23 ,0 ,88 ,11 ,6 ,11 ]) arr1.min () arr1.argmax() np.argwhere(arr1 > 20 ) np.cumsum(arr1) arr2 = np.random.randint(0 ,10 ,size = (4 ,5 )) arr2.mean(axis = 0 ) arr2.mean(axis = 1 ) np.cov(arr2,rowvar=True ) np.corrcoef(arr2,rowvar=True )
第九部分 线性代数
矩阵乘积
1 2 3 4 5 6 7 8 A = np.array([[4 ,2 ,3 ], [1 ,3 ,1 ]]) B = np.array([[2 ,7 ], [-5 ,-7 ], [9 ,3 ]]) np.dot(A,B) A @ B
矩阵其他计算
下面可以计算矩阵的逆、行列式、特征值和特征向量、qr分解值,svd分解值
1 2 3 4 5 6 7 from numpy.linalg import inv,det,eig,qr,svd A = np.array([[1 ,2 ,3 ], [2 ,3 ,4 ], [4 ,5 ,8 ]]) inv(t) det(t)
第十部分 实战 -用NumPy分析鸢尾花花萼属性各项指标
案列:读取iris数据集中的花萼长度数据(已保存为csv格式)
并对其进行排序、去重,并求出和、累积和、均值、标准差、方差、最小值、最大值。
1 2 3 4 5 6 7 8 9 10 11 12 import numpy as np data = np.loadtxt('./iris.csv' ,delimiter = ',' ) data.sort(axis = -1 ) print ('简单排序后:' , data)print ('数据去重后:' , np.unique(data)) print ('数据求和:' , np.sum (data)) print ('元素求累加和' , np.cumsum(data)) print ('数据的均值:' , np.mean(data)) print ('数据的标准差:' , np.std(data)) print ('数据的方差:' , np.var(data)) print ('数据的最小值:' , np.min (data)) print ('数据的最大值:' , np.max (data))