numpy基础和应用
数组对象基础
数组也是对象,其类型是numpy.ndarray
组成数组的元素必须是同一类型,这点与列表是不一样的。
NumPy数组对象的常用属性:
dtype:返回数组元素的类型
shape:返回由整数组成的元祖,元组中的每一个整数依次对应数组的每个轴的元素个数
size:数组中元素的个数
ndim:数组的轴的个数,即维度
nbytes:保存数组的字节数
创建数组
np.array()
object参数所引用的对象是array_like(类数组,可以是列表,元祖等可迭代序列,也可以是数组,矩阵)
numpy中创建特殊数组的函数
①同一种元素的数组
创建元素值为1的数组:ones(以元祖的形式指定形状) ones_like(指定数组)
同理 zeros,zeros_like,empty,empty_like
②np.eye() np.identity() np.diag()都能创建对角线元素比较特殊而其他部分元素为0的数组
#根据k来调整对角线的位置 data=np.eye(4,dtype=int,k=1) """ 运行结果: [[0 1 0 0] [0 0 1 0] [0 0 0 1] [0 0 0 0]] """ #而np.identity()创建的是不能调整对角线的单位矩阵 data=np.identity(4) """ [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]] """ #比较灵活的是,np.diag() data=np.diag([1,2,3,4],k=-1) """ [[0 0 0 0 0] [1 0 0 0 0] [0 2 0 0 0] [0 0 3 0 0] [0 0 0 4 0]] """ #第二个作用 data=np.arange(16).reshape((4,4)) """ [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] [12 13 14 15]] """ data1=np.diag(data,k=-1) """ [ 4 9 14] """
③创建元素是等差和等比的数组
#通过arange()函数 创建一维数组 开始值,结束值,步长 前包括后不包括 data=np.arange(1,10,3) """[1 4 7]""" #linspace() 开始值,结束值,数组的长度(数列总共有的数值的个数) # 有一个参数endpoint=True 来调控是否包含末尾的值 默认是true即包括 data=np.linspace(1,10,4) """[ 1. 4. 7. 10.]""" #返回的是等比数列元素组成的数组 data=np.logspace(2,3,num=4) """[ 100. 215.443469 464.15888336 1000. ]"""
④创建自定义类型的数组
使用方法是np.dtype()方法,注意是方法,与属性的区别
data.dtype data是数组对象,返回的是数组元素的类型
#my_type是自定义的dtype对象,参数是一个字典,字典有两个键”names“ 和”formats“ # formats规定了相应字段的类型 S30表示长度为30字节的字符串类型 my_type=np.dtype({"names":['name','age'],"formats":['S30',np.int_]}) #另一种定义方式 #my_type=np.dtype([('name','S30'),('age',np.int_)]) students=np.array([('shatinhui',21),('zhangsan',16)],dtype=my_type) # [(b'shatinhui', 21) (b'zhangsan', 16)]
数组的索引
①下标是整数
c=np.logspace(1,3,12).reshape(3,4) """ [[ 10. 15.19911083 23.101297 35.11191734] [ 53.36699231 81.11308308 123.28467394 187.38174229] [ 284.80358684 432.87612811 657.93322466 1000. ]] """ c[1][2] c[(1,2)] c[1,2] #这三种写法是一样的 """123.28467394420659"""
②下标是列表
对于一维数组,下标如果是一个列表,则可以列表中元素值为索引依次从数组中取值,并且生成一个新的数组。
b=np.linspace(0,100,5) # [ 0. 25. 50. 75. 100.] three=b[0],b[2],b[3] # (0.0, 50.0, 75.0) three2=b[[0,2,3]] # [ 0. 50. 75.] 返回的是一个数组对象,并且是一个新数组,跟原来的数组没有关系。
c=np.logspace(1,3,12).reshape(3,4) """ [[ 10. 15.19911083 23.101297 35.11191734] [ 53.36699231 81.11308308 123.28467394 187.38174229] [ 284.80358684 432.87612811 657.93322466 1000. ]] """ c[[0,2]] """ [[ 10. 15.19911083 23.101297 35.11191734] [ 284.80358684 432.87612811 657.93322466 1000. ]] """ c[[0,2],[1,2]] # [ 15.19911083 657.93322466] 相当于取c[0][1] 和c[0][2]
③下标是数组
b=np.linspace(0,100,5) b[1]=100 #[ 0. 100. 50. 75. 100.] v=np.array([0,1,3]) r=b[v] print(r) print(b[[0,1,3]]) # 结果都是[ 0. 100. 75.] #列表可以看做"类数组"对象,那么下标是数组和下标是列表的操作应该非常相似
下标是数组的情况,不局限于下标是列表的情况,看下面程序下标是布尔型数组的情况。
b=np.linspace(0,100,5) b[1]=100 #[ 0. 100. 50. 75. 100.] t=b==50 print(t) # [False False True False False] 数组元素变成布尔型 print(b[t]) #[50.] print(b[b>60]) #[100. 75. 100.]
数组的切片
切片用来设定某一范围,根据这个范围从原数组中得到部分元素。
通过切片得到的数组和原数组共享一个内存空间,通常称为公用同一视图,当其中一个进行修改时,另一个也随之修改, 这跟上面通过下标得到的新数组是不一样的,他们不共享同一存储空间。
关于切片理解方式:先根据0轴的要求进行切片,然后将得到的结果根据1轴进行切片。
练习题


数组的操作
数组变形
a=np.arange(10) #通过reshape方法对数组a变形,得到一个新数组,他们不公用同一视图 b=np.reshape(a,(2,5)) """ [[0 1 2 3 4] [5 6 7 8 9]] """ c=np.reshape(b,(-1,1)) #使用一个不存在的数,让numpy自动推断0轴上应该有的元素个数 """ [[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]] """
除使用reshape()方法外,也可以使用数组的shape属性进行变形,但这种方式不是生成一个新的数组。
将数组扁平化——变成一维数组 数组对象.flatten(),不在同一视图
相同作用的reval(),区别:在同一视图
使用下标操作完成变形
data=np.arange(5) c=data[:,np.newaxis] """ [[0] [1] [2] [3] [4]] """ #将数组的某个轴设置为np.newaxis即None data2=np.expand_dims(data,axis=1) """ [[0] [1] [2] [3] [4]] """ #np.expand_dims()作用是根据轴来调整数组形状
数组的组合
①水平组合
np.hstack(tup) tup是元祖,包含即将被组合在一起的几个数组
这几个数组要求其0轴方向的形状一致,而1轴的形状可以不同
a=np.arange(9).reshape((3,3)) b=np.arange(12).reshape((3,4)) np.hstack((a,b)) """ [[ 0 1 2 0 1 2 3] [ 3 4 5 4 5 6 7] [ 6 7 8 8 9 10 11]] """
实现水平组合的另外两种方法:
np.stack() 它要求每一个数组有相同的形状
np.concatenate((a,b),axis=1) #水平组合就是沿着1轴组合
②垂直组合
np.vstack()要求被组合的数组在1轴方向上的形状相同
同样可以使用np.concatenate()方法,传入轴的参数 axis=0
③其他组合
#深度组合 a=np.arange(9).reshape((3,3)) b=a*3 np.dstack((a,b)) """ [[[ 0 0] [ 1 3] [ 2 6]] [[ 3 9] [ 4 12] [ 5 15]] [[ 6 18] [ 7 21] [ 8 24]]] """ #深度组合,把a,b想象成两个平面,一上一下,然后沿着竖直方向组合上下对应的元素,形成三个竖直的面,它们就是新生成的数组
#列组合 one=np.arange(5) two=np.arange(5,10) np.column_stack((one,two)) """ [[0 5] [1 6] [2 7] [3 8] [4 9]] """ #行组合 np.row_stack((one,two)) """ [[0 1 2 3 4] [5 6 7 8 9]] """
数组的分割
a=np.arange(24).reshape((4,6)) np.split(a,2,axis=1) """ [array([[ 0, 1, 2], [ 6, 7, 8], [12, 13, 14], [18, 19, 20]]), array([[ 3, 4, 5], [ 9, 10, 11], [15, 16, 17], [21, 22, 23]])] """ np.hsplit(a,2) """ [array([[ 0, 1, 2], [ 6, 7, 8], [12, 13, 14], [18, 19, 20]]), array([[ 3, 4, 5], [ 9, 10, 11], [15, 16, 17], [21, 22, 23]])] """ np.vsplit(a,2) """ [array([[ 0, 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10, 11]]), array([[12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23]])] """
改编元素
改编元素是指修改数组已有元素(通过索引),增加,修改元素(通过np.append(),np.insert(),np.delete()三个方法,实质都是创建了一个新的数组,跟原来数组没有关系)
a=np.array([[1,2,3],[4,5,6]]) b=np.array([[7,8,9]]) r=np.append(a,b,axis=0) """ [[1 2 3] [4 5 6] [7 8 9]] """ a1=a.flatten() r=np.insert(a1,1,88) # [ 1 88 2 3 4 5 6] np.delete(a,1,axis=0) # [[1 2 3]]
运算
①算数运算
一个数组和一个标量进行加、减、乘、除运算,结果是数组的每一个元素都与该标量进行相应的运算,并返回一个新数组。
原则上,只有形状一样的数组才能进行运算。
某种情况,就是numpy将某个数组通过广播的方式进行临时转换,使得两个数组的形状符合原则上的要求
a=np.arange(10).reshape(2,5) m=np.arange(5) a+m #两个数组在1轴上长度一样 """ [[ 0 2 4 6 8] [ 5 7 9 11 13]] """ n=np.arange(1,3).reshape(-1,1) #两个数组在0轴上长度一致 print(a+n) """ [[ 1 2 3 4 5] [ 7 8 9 10 11]] """
②比较运算和逻辑运算
比较运算要求两个数组的形状一样,一一对应地进行比较,然后以布尔型数组形式返回比较结果
a=np.array([3,6,9]) b=np.array([4,5,8]) print(np.any(a<b) and np.any(a>b)) #True print(np.all(a<b)) #False print((a<b).all()) #False
通用函数
①内置函数 常用的一元函数和二元函数,用的时候查表
②自定义通用函数
def bmi(height,weight): bmi_index=weight/height**2 if bmi_index>=18 and bmi_index<=25: return 0 elif bmi_index<18: return -1 else: return 1 #np.random随机抽样 #其random_sample()方法返回随机的浮点数,在[0.0,1.0)之间 #所以要产生[a,b)随机的浮点数,(b-a)*np.random.random_sample()+a h=(2.1-1.4)*np.random.random_sample((10,))+1.4 h=np.round(h,2) #四舍五入,保留2位小数 w=(100-40)*np.random.random_sample((10,))+40 w=np.round(w,2) #第一种方式 #使用np.frompyfunc() 使之成为能够针对数组元素进行操作的函数 bmi_ufunc=np.frompyfunc(bmi,2,1) #bmi函数接收的参数为2个,返回的对象1个 print(bmi_ufunc(h,w)) #[1 0 1 1 1 1 0 0 -1 0] #第二种方式 #np.vectorize() 将函数对象矢量化 bmi_ufunc2=np.vectorize(bmi,otypes=[np.float_]) #通过otypes设置返回数组的元素类型 print(bmi_ufunc2(h,w)) #[ 1. 0. 0. 0. 0. 1. 1. -1. 0. 1.]
简单统计应用
1.生成正态分布数据 +统计函数的使用
np.random.normal([loc, scale, size])
loc即μ 分布的平均值,scale即 分布的标准差,size为输出的数据个数
np.random.randn(size) 生成标准正态分布
g=np.random.randn(10) g1=np.random.randn(10) g=(g-g.min())/10 #这两个语句什么意思,为什么要除以10 g1=(g1-g1.min())/10 math=np.round((100-40)*g+40,1) english=np.round((100-40)*g1+40,1) marks=np.vstack((math,english)) #垂直组合 """ [[50.9 45.3 44.3 54.3 41.6 40. 46.5 47.6 43.4 49.9] [45.9 51.4 46.9 50.5 60.6 40. 45.9 50.8 46.9 49.3]] """ print(np.mean(marks,axis=1)) #在1轴上计算平均值,那么就是英语和数学的平均值 print(np.mean(marks,axis=0)) #在0轴上计算平均值,就是每个学生两门成绩的平均值 #np.where()函数的使用 有点像三元操作符 print(np.where(math>np.mean(math),'好','差')) #['差' '差' '差' '好' '好' '差' '好' '差' '好' '差'] print(np.where(math>np.mean(math))) # (array([1, 2, 3, 5, 8], dtype=int64),) 返回的是符合条件的元素索引组成的数组 #np.select()的使用 """ 比平均分高5分的为好 比平均分高但少于5分的为良 其他为中 """ print(np.select([math>np.mean(math)+5,np.logical_and(math>=np.mean(math),math<=np.mean(math)+5)], ['好','良'],default='中')) #['好' '好' '好' '中' '良' '中' '中' '中' '中' '中'] #np.piecewise() """ 第一个参数 对象 第二个参数 条件列表 第三个参数 执行的操作列表 第二个参数和第三个参数要相对应 返回一个array对象 """ print(np.piecewise(math,[math>np.mean(math)+5,np.logical_and(math>=np.mean(math),math<=np.mean(math)+5)], [100,60])) #[100. 0. 60. 60. 0. 100. 0. 60. 0. 0.]
矩阵
矩阵是ndarray的子类,因此它继承了数组的属性和方法,然后也有自己特有的属性和方法(矩阵乘法,矩阵幂)
创建矩阵
a=np.mat([1,2,3]) # [[1 2 3]] a=np.mat('1 2 3;4 5 6;7 8 9') #以字符串作为参数来创建矩阵 """ [[1 2 3] [4 5 6] [7 8 9]] """ a1=np.mat(np.arange(10)) #也可以以数组作为参数创建矩阵 #也可以以矩阵为参数创建新的矩阵 m1=np.mat(np.eye(2)) m2=2*m1 r=np.bmat('m1 m2;m2 m1') """ [[1. 0. 2. 0.] [0. 1. 0. 2.] [2. 0. 1. 0.] [0. 2. 0. 1.]] """
矩阵的乘法
如果对二维数组的操作,实现类似乘法的操作,函数是np.dot()
a=np.arange(1,10).reshape(3,3) b=np.array([[1,0,1],[0,1,1],[1,1,0]]) print(a*b) #两个矩阵的对应元素相乘 """ [[1 0 3] [0 5 6] [7 8 0]] """ print(np.mat(a)*np.mat(b)) #矩阵乘法 print(np.dot(a,b)) #点乘,实现矩阵乘法,还有其他用途,在下面 """ [[ 4 5 3] [10 11 9] [16 17 15]] """
基本操作
转置 A.T
逆矩阵 A.I
矩阵幂
numpy有一个专门的模块来针对线性代数,模块名称为linalg(Linear algebra),可以完成更多矩阵的计算,包括求特征值,解线性方程组,计算行列式等
矢量运算
标量:只有大小没有方向
矢量:既有大小,右有方向
矢量与矢量的加减运算
f1=np.array([10*math.cos(math.pi/6),10*math.sin(math.pi/6)]) f2=np.array([0,12]) f=f1+f2 print(np.sqrt(np.sum(f**2))) #在没有别的参数的情况下,np.linalg.norm输入一个vector, # 就是计算vector的长度:vector的每个component的平方相加后开根号。 print(np.linalg.norm(f))
标量积
也叫数量积,点积,内积
两个矢量相乘的结果是标量
前面用过的np.dot():
对于一维数组,就是进行标量积运算(比如求做功,功=力*位移,两个都是矢量)
对于二维数组,就是矩阵乘法
一维数组除了使用np.dot()进行标量积运算外,我们还可以使用np.inner(),两者在一维无区别,对于多维是有区别的,如下

矢量积
又叫叉积或者外积,其结果也是矢量,方向是与两个矢量所构成的平面垂直
使用np.cross()求解矢量积(比如,求三个点围成的三角形面积)
观察np.outer() ,参数对象是一维数组表示的矢量,如果不是一维数组,自动将其展平为一维数组
v=np.array([1,2,3]) b=np.array([9,8,7]) print(np.outer(v,b)) """ [[ 9 8 7] [18 16 14] [27 24 21]] """
张量积
这个之前没有听过
np.tensordot()的使用
a=np.arange(6).reshape(2,3) b=np.arange(9).reshape(3,3) print(np.dot(a,b)) print(np.tensordot(a,b,axes=([1],[0]))) #根据标量积的规则,a的1轴上的各元素与b的0轴上的各元素对应相乘并求和 """ [[15 18 21] [42 54 66]] """
下面这段,不是很懂
c=np.random.randint(2,size=(2,3,5)) d=np.random.randint(2,size=(3,2,4)) print(np.tensordot(c,d,axes=((0,1),(1,0)))) """ [[1 1 2 2] [1 1 2 1] [1 0 1 1] [2 1 3 2] [0 2 1 2]] """
综合应用示列
多项式
补充一点:lambda函数
lambda匿名函数的格式:冒号前是参数,可以有多个,用逗号隔开,冒号右边为表达式,返回值是函数的地址,也就是函数对象
#使用numpy.ploy1d(),以一维数组为参数,创建一个多项式 a=np.array([1,-2,1]) p=np.poly1d(a) """ 2 1 x - 2 x + 1 """ #创建 f(x)=(x-1)的平方+3(x-1)+1 g=np.poly1d([1,3,1]) f=lambda x:g(x-1) print(f(1)) #结果为1
numpy.ploy1d(c_or_r,r=False,variable=None)
参数r=False(默认) 表示多项式的系数 ,如果 r=True表示多项式的根
variable表示多项式变量的符号,它接收的是一个字符串
a=np.array([1,-2,1]) p=np.poly1d(a,r=True,variable='a') """ 3 1 a - 3 a + 2 """
多项式计算
#多项式加减乘除 #可以把类数组对象直接与多项式计算 a=np.array([1,-2,1]) p=np.poly1d(a) print(p+[-1,1]) """ 2 1 x - 3 x + 2 """ print(p/[-1,1]) #除法注意余数 """ (poly1d([-1., 1.]), poly1d([0.])) """ #微分 print(p.deriv()) #2 x - 2 #积分(integral) print(p.integ()) """ 3 2 0.3333 x - 1 x + 1 x """ #求多项式的根 print(np.roots(p)) # [1. 1.]
拟合多项式
对某些数据使用多项式函数进行拟合的方法:numpy.polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False),前三个参数是必须的,第三个参数表示多项式次数
提供多项式操作方法的模块 numpy.polynomial
求解线性方程组
""" 求解方程组 3a+b=9 a+2b=8 """ a=np.array([[3,1],[1,2]]) b=np.array([9,8]) x=np.linalg.solve(a,b) #[2. 3.]

浙公网安备 33010602011771号