Python科学计算与数据处理.ppt

上传人:小飞机 文档编号:5445811 上传时间:2023-07-07 格式:PPT 页数:103 大小:412KB
返回 下载 相关 举报
Python科学计算与数据处理.ppt_第1页
第1页 / 共103页
Python科学计算与数据处理.ppt_第2页
第2页 / 共103页
Python科学计算与数据处理.ppt_第3页
第3页 / 共103页
Python科学计算与数据处理.ppt_第4页
第4页 / 共103页
Python科学计算与数据处理.ppt_第5页
第5页 / 共103页
点击查看更多>>
资源描述

《Python科学计算与数据处理.ppt》由会员分享,可在线阅读,更多相关《Python科学计算与数据处理.ppt(103页珍藏版)》请在三一办公上搜索。

1、NumPy快速处理数据,1,2,NumPy,ndarray 对象,目录,NumPy的导入创建数组存取元素多维数组结构数组,3,NumPy的导入,标准的Python 中用列表(list)保存一组值,可以当作数组使用。但由于列表的元素可以是任何对象,因此列表中保存的是对象的指针。对于数值运算来说,这种结构显然比较浪费内存和CPU计算Python 提供了array 模块,它和列表不同,能直接保存数值,但是由于它不支持多维数组,也没有各种运算函数,因此也不适合 做数值运算。,4,NumPy的导入,NumPy 的诞生弥补了这些不足,NumPy 提供了两种基本的对象:ndarray(n-dimension

2、al array object)和ufunc(universal function object)。ndarray(下文统一称之为数组)是存储单一数据类型的多维数组,而ufunc 则是能够对数组进行处理的函数。函数库的导入,5,import numpy as np,创建数组,在IPython 中输入函数名并添加一个“?”符号,就可以显示文档内容。例如,输入“np.array?”可以通过给array函数传递Python的序列对象创建数组,如果传递的是多层嵌套的序列,将创建多维数组(下例中的变量c):,6,创建数组,7,a=np.array(1,2,3,4)b=np.array(5,6,7,8)c

3、=np.array(1,2,3,4,4,5,6,7,7,8,9,10)barray(5,6,7,8)carray(1,2,3,4,4,5,6,7,7,8,9,10)c.dtype#数组的元素类型可以通过dtype 属性获得dtype(int32),创建数组,数组的大小可以通过其shape属性获得:可以通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度。,8,a.shape#一维数组(4,)c.shape#二维数组其中第0 轴的长度为3,第1 轴的长度为4。(3,4),c.shape=4,3#注意从(3,4)改为(4,3)并不是对数组进行转置,而只是改变每个轴的大

4、小,数组元素在内存中的位置并没有改变:carray(1,2,3,4,4,5,6,7,7,8,9,10),创建数组,9,d=a.reshape(2,2)#使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变。darray(1,2,3,4)aarray(1,2,3,4),c.shape=2,-1#当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度,因此下面的程序将数组c的shape改为了(2,6)。carray(1,2,3,4,4,5,6,7,7,8,9,10),创建数组,数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改

5、另外一个数组。,10,a1=100#将数组a的第一个元素改为100 d#注意数组d中的2也被改变了array(1,100,3,4),创建数组,数组的元素类型可以通过dtype属性获得。可以通过dtype参数在创建时指定元素类型:,11,np.array(1,2,3,4,4,5,6,7,7,8,9,10,dtype=np.float)array(1.,2.,3.,4.,4.,5.,6.,7.,7.,8.,9.,10.)np.array(1,2,3,4,4,5,6,7,7,8,9,10,dtype=plex)array(1.+0.j,2.+0.j,3.+0.j,4.+0.j,4.+0.j,5.+0

6、.j,6.+0.j,7.+0.j,7.+0.j,8.+0.j,9.+0.j,10.+0.j),创建数组,上面的例子都是先创建一个Python序列,然后通过array函数将其转换为数组,这样做显然效率不高。因此NumPy提供了很多专门用来创建数组的函数。arange函数类似于python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值:,12,np.arange(0,1,0.1)array(0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),创建数组,linspace函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoin

7、t关键字指定是否包括终值,缺省设置是包括终值:,13,np.linspace(0,1,10)#步长为1/9array(0.,0.11111111,0.22222222,0.33333333,0.44444444,0.55555556,0.66666667,0.77777778,0.88888889,1.)np.linspace(0,1,10,endpoint=False)#步长为1/10array(0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),创建数组,logspace函数和linspace类似,不过它创建等比数列,下面的例子产生1(100)到100(102)

8、、有20个元素的等比数列:,14,np.logspace(0,2,20)array(1.,1.27427499,1.62377674,2.06913808,2.6366509,3.35981829,4.2813324,5.45559478,6.95192796,8.8586679,11.28837892,14.38449888,18.32980711,23.35721469,29.76351442,37.92690191,48.32930239,61.58482111,78.47599704,100.),创建数组,zeros()、ones()、empty()可以创建指定形状和类型的数组。此外,

9、zeros_like()、ones_like()、empty_like()等函数可创建与参数数组的形状及类型相同的数组。因此,“zeros_like(a)”和“zeros(a.shape,a.dtype)”的效果相同。,15,np.empty(2,3),np.int)#只分配内存,不对其进行初始化array(32571594,32635312,505219724,45001384,1852386928,665972)?np.zeros(4,np.float)#元素类型默认为np.float,因此这里可以省略array(0.,0.,0.,0.),创建数组,此外,使用frombuffer,from

10、string,fromfile,fromfunction等函数可以从字节序列、文件创建数组,下面以fromfunction为例:np.fromfunction?fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape)。,16,def func(i):.return i%4+1.np.fromfunction(func,(10,)array(1.,2.,3.,4.,1.,2.,3.,4.,1.,2.),创建数组,17,下面的例子创建一个二维数组表示九九乘法表,输出的数组a中的每个元素ai,j都等于func2(i,j):,def func2(i,j):

11、.return(i+1)*(j+1).a=np.fromfunction(func2,(9,9)aarray(1.,2.,3.,4.,5.,6.,7.,8.,9.,2.,4.,6.,8.,10.,12.,14.,16.,18.,3.,6.,9.,12.,15.,18.,21.,24.,27.,4.,8.,12.,16.,20.,24.,28.,32.,36.,5.,10.,15.,20.,25.,30.,35.,40.,45.,6.,12.,18.,24.,30.,36.,42.,48.,54.,7.,14.,21.,28.,35.,42.,49.,56.,63.,8.,16.,24.,32.

12、,40.,48.,56.,64.,72.,9.,18.,27.,36.,45.,54.,63.,72.,81.),存取元素,数组元素的存取方法和Python的标准方法相同:,18,a=np.arange(10)a5#用整数作为下标可以获取数组中的某个元素5 a3:5#用范围作为下标获取数组的一个切片,包括a3不包括a5array(3,4)a:5#省略开始下标,表示从a0开始array(0,1,2,3,4)a:-1#下标可以使用负数,表示从数组后往前数array(0,1,2,3,4,5,6,7,8)a2:4=100,101#下标还可以用来修改元素的值 aarray(0,1,100,101,4,5

13、,6,7,8,9)a1:-1:2#范围中的第三个参数表示步长,2表示隔一个元素取一个元素,存取元素,19,array(1,101,5,7)a:-1#省略范围的开始下标和结束下标,步长为-1,整个数组头尾颠倒array(9,8,7,6,5,4,101,100,1,0)a5:1:-2#步长为负数时,开始下标必须大于结束下标array(5,101),存取元素,和Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间:,20,b=a3:7#通过下标范围产生一个新的数组b,b和a共享同一块数据空间 barray(101,4,5,6)b2=-10#将b的

14、第2个元素修改为-10 barray(101,4,-10,6)a#a的第5个元素也被修改为10array(0,1,100,101,4,-10,6,7,8,9),存取元素,除了使用下标范围存取元素之外,NumPy还提供了两种存取元素的高级方法。使用整数序列 当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间。,21,x=np.arange(10,1,-1)xarray(10,9,8,7,6,5,4,3,2),存取元素,22,x3,3,1,8#获取x中的下标为3,3,1,8的4个元素,组成一个新

15、的数组array(7,7,9,2)b=xnp.array(3,3,-3,8)#下标可以是负数 b2=100 barray(7,7,100,2)x#由于b和x不共享数据空间,因此x中的值并没有改变array(10,9,8,7,6,5,4,3,2)x3,5,1=-1,-2,-3#整数序列下标也可以用来修改元素的值 xarray(10,-3,8,-1,6,-2,4,3,2),存取元素,使用布尔数组 当使用布尔数组b作为下标存取数组x中的元素时,将收集数组x中所有在数组b中对应下标为True的元素。使用布尔数组作为下标获得的数组不和原始数组共享数据空间,注意这种方式只对应于布尔数组,不能使用布尔列表。

16、,23,x=np.arange(5,0,-1)xarray(5,4,3,2,1),存取元素,24,xnp.array(True,False,True,False,False)#布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素array(5,3)xTrue,False,True,False,False#如果是布尔列表,则把True当作1,False当作0,按照整数序列方式获取x中的元素array(4,5,4,5,5)xnp.array(True,False,True,True)#布尔数组的长度不够时,不够的部分都当作Falsearray(5,3,2)xnp.array(Tr

17、ue,False,True,True)=-1,-2,-3#布尔数组下标也可以用来修改元素 xarray(-1,4,-2,-3,1),存取元素,布尔数组一般不是手工产生,而是使用布尔运算的ufunc函数产生。,25,x=np.random.rand(10)#产生一个长度为10,元素值为0-1的随机数的数组 xarray(0.72223939,0.921226,0.7770805,0.2055047,0.17567449,0.95799412,0.12015178,0.7627083,0.43260184,0.91379859),存取元素,26,x0.5#数组x中的每个元素和0.5进行大小比较,得

18、到一个布尔数组,True表示x中对应的值大于0.5array(True,True,True,False,False,True,False,True,False,True,dtype=bool)xx0.5#使用x0.5返回的布尔数组收集x中的元素,因此得到的结果是x中所有大于0.5的元素的数组array(0.72223939,0.921226,0.7770805,0.95799412,0.7627083,0.91379859),多维数组,多维数组的存取和一维数组类似,因为多维数组有多个轴,因此它的下标需要用多个值来表示,NumPy采用组元(tuple)作为数组的下标。如下图所示,a为一个6x6的

19、数组,图中用颜色区分了各个下标以及其对应的选择区域。组元不需要圆括号 虽然我们经常在Python中用圆括号将组元括起来,但是其实组元的语法定义只需要用逗号隔开即可,例如x,y=y,x 就是用组元交换变量值的一个例子。,27,多维数组,如下图所示,a为一个6x6的数组,图中用颜色区分了各个下标以及其对应的选择区域。,28,多维数组,如何创建这个数组:数组a实际上是一个加法表,纵轴的值为0,10,20,30,40,50;横轴的值为0,1,2,3,4,5。纵轴的每个元素都和横轴的每个元素求和,就得到图中所示的数组a。你可以用下面的语句创建它。,29,np.arange(0,60,10).reshap

20、e(-1,1)+np.arange(0,6)array(0,1,2,3,4,5,10,11,12,13,14,15,20,21,22,23,24,25,30,31,32,33,34,35,40,41,42,43,44,45,50,51,52,53,54,55),多维数组,多维数组同样也可以使用整数序列和布尔数组进行存取。,30,多维数组,a(0,1,2,3,4),(1,2,3,4,5):用于存取数组的下标和仍然是一个有两个元素的组元,组元中的每个元素都是整数序列,分别对应数组的第0轴和第1轴。从两个序列的对应位置取出两个整数组成下标:a0,1,a1,2,.,a4,5。a3:,0,2,5:下标中

21、的第0轴是一个范围,它选取第3行之后的所有行;第1轴是整数序列,它选取第0,2,5三列。amask,2:下标的第0轴是一个布尔数组,它选取第0,2,5行;第1轴是一个整数,选取第2列。,31,结构数组,假设需要定义一个结构数组,它的每个元素都有name,age和weight字段。在NumPy中可以如下定义:文件名:numpy_struct_array.py,32,import numpy as nppersontype=np.dtype(names:name,age,weight,formats:S32,i,f)a=np.array(Zhang,32,75.5),(Wang,24,65.2),

22、dtype=persontype)run numpy_struct_array.py a.dtypedtype(name,|S32),(age,i4),(weight,f4),结构数组,一种描述结构类型的方法:一个包含多个组元的列表,其中形如(字段名,类型描述)的组元描述了结构中的每个字段。类型描述前面为我们添加了|,:高位字节在前,33,结构数组,结构数组的存取方式和一般数组相同,通过下标能够取得其中的元素,注意元素的值看上去像是组元,实际上它是一个结构:a0是一个结构元素,它和数组a共享内存数据,因此可以通过修改它的字段,改变原始数组中的对应字段:,34,a0(Zhang,32,75.5)

23、a0.dtypedtype(name,|S32),(age,i4),(weight,f4),c=a1 cname=Li a1nameLi”结构,结构数组,35,结构像字典一样可以通过字符串下标获取其对应的字段值:不但可以获得结构元素的某个字段,还可以直接获得结构数组的字段,它返回的是原始数组的视图,因此 可以通过修改 b0改变 a0age:,b=a:age#或者aage barray(32,24)b0=40 a0age40,a0nameZhang,36,NumPy,ufunc运算,目录,ufunc运算简介广播ufunc的方法,37,ufunc运算简介,ufunc是universal funct

24、ion的缩写,它是一种能对数组的每个元素进行操作的函数。NumPy内置的许多ufunc函数都是在C语言级别实现的,因此它们的计算速度非常快。,38,#对数组x中的每个元素进行正弦计算,返回一个同样大小的新数组 x=np.linspace(0,2*np.pi,10)y=np.sin(x)yarray(0.00000000e+00,6.42787610e-01,9.84807753e-01,8.66025404e-01,3.42020143e-01,-3.42020143e-01,-8.66025404e-01,-9.84807753e-01,-6.42787610e-01,-2.44921271

25、e-16),ufunc运算简介,计算之后x中的值并没有改变,而是新创建了一个数组保存结果。如果希望将sin函数所计算的结果直接覆盖到数组x上去的话,可以将要被覆盖的数组作为第二个参数传递给ufunc函数。例如:,39,t=np.sin(x,x)xarray(0.00000000e+00,6.42787610e-01,9.84807753e-01,8.66025404e-01,3.42020143e-01,-3.42020143e-01,-8.66025404e-01,-9.84807753e-01,-6.42787610e-01,-2.44921271e-16)id(t)=id(x)True,

26、ufunc运算简介,用下面这个小程序,比较了一下numpy.math和Python标准库的math.sin的计算速度:(numpy_speed_test.py),40,import timeimport mathimport numpy as npx=i*0.001 for i in xrange(1000000)start=time.clock()for i,t in enumerate(x):xi=math.sin(t)print math.sin:,time.clock()-start,ufunc运算简介,41,x=i*0.001 for i in xrange(1000000)x=np

27、.array(x)start=time.clock()np.sin(x,x)print numpy.sin:,time.clock()startx=i*0.001 for i in xrange(1000000)start=time.clock()for i,t in enumerate(x):xi=np.sin(t)print numpy.sin loop:,time.clock()start#输出#numpy.sin:0.0882399858083#numpy.sin loop:5.72166965355,ufunc运算简介,numpy.sin的计算速度只有math.sin的1/5。这是因

28、为numpy.sin为了同时支持数组和单个值的计算,其C语言的内部实现要比math.sin复杂很多。numpy.sin比math.sin快10倍多。这得利于numpy.sin在C语言级别的循环计算。numpy.sin同样也支持对单个数值求正弦,不过对单个数的计算math.sin则比numpy.sin快得多了。,42,ufunc运算简介,此外,numpy.sin返回的数的类型和math.sin返回的类型有所不同,math.sin返 回的是Python的标准float类型,而numpy.sin则返回一个numpy.float64类型:因为它们各有长短,因此在导入时不建议使用*号全部载入,而是应该使

29、用import numpy as np的方式载入,这样可以根据需要选择合适的函数调用。,43,type(math.sin(0.5)type(np.sin(0.5),ufunc运算简介,四则运算:NumPy中有众多的ufunc函数提供各式各样的计算。,44,a=np.arange(0,4)aarray(0,1,2,3)b=np.arange(1,5)barray(1,2,3,4)np.add(a,b)array(1,3,5,7)np.add(a,b,a)#第3个参数指定计算结果所要写入的数组,如果指定的话,add函数就不再产生新的数组。array(1,3,5,7)aarray(1,3,5,7),

30、ufunc运算简介,由于Python的操作符重载功能,计算两个数组相加可以简单地写为a+b,而np.add(a,b,a)则可以用a+=b来表示。下面是数组的运算符和其对应的ufunc函数的一个列表,注意除号/的意义根据是否激活_future_.division有所不同。,45,y=x1+x2:add(x1,x2,y)y=x1-x2:subtract(x1,x2,y)y=x1*x2:multiply(x1,x2,y)y=x1/x2:divide(x1,x2,y),如果两个数组的元素为整数,那么用整数除法y=x1/x2:true divide(x1,x2,y),总是返回精确的商y=x1/x2:fl

31、oor divide(x1,x2,y),总是对返回值取整y=-x:negative(x,y)y=x1*x2:power(x1,x2,y)y=x1%x2:remainder(x1,x2,y),mod(x1,x2,y),ufunc运算简介,数组对象支持这些操作符,极大地简化了算式的编写,不过要注意如果你的算式很复杂,并且要运算的数组很大的话,会因为产生大量的中间结果而降低程序的运算效率。例如:假设a b c三个数组采用算式x=a*b+c计算,那么它相当于:也就是说需要产生一个数组t保存乘法的计算结果,然后再产生最后的结果数组x。我们可以通过手工将一个算式分解为x=a*b;x+=c,以减少一次内存分

32、配。,46,t=a*bx=t+cdel t,ufunc运算简介,比较和布尔运算:使用“=”、“”等比较运算符对两个数组进行比较,将返回一个布尔数组,它的每个元素值都是两个数组对应元素的比较结果。例如:,47,np.array(1,2,3)np.array(3,2,1)array(True,False,False,dtype=bool),ufunc运算简介,每个比较运算符也与一个ufunc函数对应,下面是比较运算符和其ufunc函数的:,48,y=x1=x2 equal(x1,x2,y)y=x1!=x2 not_equal(x1,x2,y)y=x1 x2 greater(x1,x2,y)y=x1

33、=x2 greater_equal(x1,x2,y),ufunc运算简介,由于Python中的布尔运算使用and、or和not等关键字,它们无法被重载,因此数组的布尔运算只能通过相应的ufunc函数进行。这些函数名都以“logical_”开头,在IPython中使用自动补全即可找到它们.,49,a=np.arange(5)b=np.arange(4,-1,-1)a=b array(False,False,True,False,False,dtype=bool)a b array(False,False,False,True,True,dtype=bool)np.logical_or(a=b,a

34、b)#和 a=b 相同 array(False,False,True,True,True,dtype=bool),ufunc运算简介,可以使用数组的any()或all()方法。只要数组中有一个值为True,则any()返回True;而只有数组的全部元素都为True,all()才返回True。,50,np.any(a=b)True np.any(a=b)and np.any(ab)True,ufunc运算简介,自定义ufunc函数:通过组合标准的ufunc函数的调用,可以实现各种算式的数组计算。不过有些时候这种算式不易编写,而针对每个元素的计算函数却很容易用Python实现,这时可以用fromp

35、yfunc函数将一个计算单个元素的函数转换成ufunc函数。这样就可以方便地用所产生的ufunc函数对数组进行计算了。,51,ufunc运算简介,用一个分段函数描述三角波,三角波的样子如下:,52,ufunc运算简介,根据上图所示写出如下的计算三角波某点y坐标的函数:显然triangle_wave函数只能计算单个数值,不能对数组直接进行处理。,53,def triangle_wave(x,c,c0,hc):x=x-int(x)#三角波的周期为1,因此只取x坐标的小数部分进行计算 if x=c:r=0.0 elif x c0:r=x/c0*hc else:r=(c-x)/(c-c0)*hc re

36、turn r,ufunc运算简介,可以先使用列表包容(List comprehension),计算出一个list,然后用array函数将列表转换为数组:这种做法每次都需要使用列表包容语法调用函数,对于多维数组是很麻烦的。让我们来看看如何用frompyfunc函数来解决这个问题:,54,x=np.linspace(0,2,1000)y1=np.array(triangle_wave(t,0.6,0.4,1.0)for t in x),ufunc运算简介,通过frompyfunc()可以将计算单个值的函数转换为一个能对数组的每个元素进行计算的ufunc函数。frompyfunc()的调用格式为:其

37、中func是计算单个元素的函数,nin是func的输入参数的个数,nout是func的返回值个数。下面的程序使用frompyfunc()将triangle_wave()转换为一个ufunc函数对象triangle_ufunc1:,55,frompyfunc(func,nin,nout),ufunc运算简介,56,triangle_ufunc2=np.frompyfunc(lambda x:triangle_wave(x,0.6,0.4,1.0),1,1)y3=triangle_ufunc2(x),虽然triangle_wave函数有4个参数,但是由于后三个c,c0,hc在整个计算中值都是固定的

38、,因此所产生的ufunc函数其实只有一个参数。为了满足这个条件,可用一个lambda函数对triangle_wave的参数进行一次包装。这样传入frompyfunc的函数就只有一个参数了。,triangle_ufunc1=np.frompyfunc(triangle_wave,4,1)y2=triangle_ufunc1(x,0.6,0.4,1.0),ufunc运算简介,值得注意的是,triangle_ufunc1()所返回的数组的元素类型是object,因此还需要再调用数组的astype()方法将其转换为双精度浮点数组:,57,y2.dtype dtype(object)y2=y2.asty

39、pe(np.float)y2.dtype dtype(float64)y3.dtype dtype(object)y3=y3.astype(np.float)y3.dtype dtype(float64),ufunc运算简介,使用vectorize()也可以实现和frompyfunc()类似的功能,但它可以通过otypes参数指定返回数组的元素类型。otypes参数可以是一个表示元素类型的字符串,或者是一个类型列表,使用列表可以描述多个返回数组的元素类型。下面的程序使用vectorize()计算三角波:,58,triangle_ufunc3=np.vectorize(triangle_wave

40、,otypes=np.float)y4=triangle_ufunc3(x,0.6,0.4,1.0),ufunc运算简介,最后验证一下结果:,59,np.all(y1=y2)True np.all(y2=y3)True np.all(y3=y4)True,广播,当我们使用ufunc函数对两个数组进行计算时,ufunc函数会对这两个数组的对应元素进行计算,因此它要求这两个数组有相同的大小(shape相同)。如果两个数组的shape不同的话,会进行如下的广播(broadcasting)处理:,60,广播,1.让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分都通过在前面加1补齐

41、。2.输出数组的shape是输入数组shape的各个轴上的最大值。3.如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错。4.当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值。,61,广播,看一个实际的例子。先创建一个二维数组a,其shape为(6,1):再创建一维数组b,其shape为(5,):,62,a=np.arange(0,60,10).reshape(-1,1)aarray(0,10,20,30,40,50)a.shape(6,1),b=np.arange(0,5)barray(0,1,2,3,4)b.shape(5,)

42、,广播,计算a和b的和,得到一个加法表,它相当于计算a,b中所有元素组的和,得到一个shape为(6,5)的数组:,63,c=a+b carray(0,1,2,3,4,10,11,12,13,14,20,21,22,23,24,30,31,32,33,34,40,41,42,43,44,50,51,52,53,54)c.shape(6,5),广播,由于a和b的shape长度(也就是ndim属性)不同,根据规则1,需要让b的shape向a对齐,于是将b的shape前面加1,补齐为(1,5)。相当于做了如下计算:这样加法运算的两个输入数组的shape分别为(6,1)和(1,5),根据规则2,输出数

43、组的各个轴的长度为输入数组各个轴上的长度的最大值,可知输出数组的shape为(6,5)。,64,b.shape=1,5 barray(0,1,2,3,4),广播,由于b的第0轴上的长度为1,而a的第0轴上的长度为6,因此为了让它们在第0轴上能够相加,需要将b在第0轴上的长度扩展为6,这相当于:,65,b=b.repeat(6,axis=0)barray(0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4),广播,由于a的第1轴的长度为1,而b的第一轴长度为5,因此为了让它们在第1轴上能够相加,需要将a在第1轴上的长度扩展为5,

44、这相当于:经过上述处理之后,a和b就可以按对应元素进行相加运算了。,66,a=a.repeat(5,axis=1)aarray(0,0,0,0,0,10,10,10,10,10,20,20,20,20,20,30,30,30,30,30,40,40,40,40,40,50,50,50,50,50),广播,numpy在执行a+b运算时,其内部并不会真正将长度为1的轴用repeat函数进行扩展,如果这样做的话就太浪费空间了。由于这种广播计算很常用,因此numpy提供了一个快速产生如上面a,b数组的方法:ogrid对象:,67,x,y=np.ogrid0:5,0:5 xarray(0,1,2,3,4

45、)yarray(0,1,2,3,4),广播,ogrid是一个很有趣的对象,它像一个多维数组一样,用切片组元作为下标进行存取,返回的是一组可以用来广播计算的数组。其切片下标有两种形式:开始值:结束值:步长,和np.arange(开始值,结束值,步长)类似 开始值:结束值:长度j,当第三个参数为虚数时,它表示返回的数组的长度,和np.linspace(开始值,结束值,长度)类似:,68,广播,ogrid为什么不是函数:根据Python的语法,只有在中括号中才能使用用冒号隔开的切片语法,如果ogrid是函数的话,那么这些切片必须使用slice函数创建,这显然会增加代码的长度。,69,x,y=np.o

46、grid0:1:4j,0:1:3j xarray(0.,0.33333333,0.66666667,1.)yarray(0.,0.5,1.),广播,利用ogrid的返回值,能很容易计算x,y网格面上各点的值,或者x,y,z网格体上各点的值。下面是绘制三维曲面x*exp(x*2-y*2)的程序:(numpy_orid_mlab.py),70,import numpy as npfrom mayavi import mlabx,y=np.ogrid-2:2:20j,-2:2:20jz=x*np.exp(-x*2-y*2)pl=mlab.surf(x,y,z,warp_scale=auto)mlab

47、.axes(xlabel=x,ylabel=y,zlabel=z)mlab.outline(pl)mlab.show,广播,此程序使用mayavi的mlab库快速绘制3D曲面,关于mlab的相关内容将在今后的章节进行介绍。,71,ufunc的方法,ufunc函数本身还有些方法,这些方法只对两个输入一个输出的ufunc函数有效,其它的ufunc对象调用这些方法时会抛出ValueError异常。reduce 方法和Python的reduce函数类似,它沿着axis轴对array进行操作.,72,np.add.reduce(1,2,3)#1+2+36 np.add.reduce(1,2,3,4,5,

48、6,axis=1)#(1+2+3),(4+5+6)array(6,15)np.add.reduce(1,2,3,4,5,6,axis=0)array(5,7,9),ufunc的方法,accumulate 方法和reduce方法类似,只是它返回的数组和输入的数组的shape相同,保存所有的中间计算结果:,73,np.add.accumulate(1,2,3)array(1,3,6)np.add.accumulate(1,2,3,4,5,6,axis=1)array(1,3,6,4,9,15),ufunc的方法,reduceat 方法计算多组reduce的结果,通过indices参数指定一系列re

49、duce的起始和终了位置。reduceat的计算有些特别,让我们通过一个例子来解释一下:,74,a=np.array(1,2,3,4)result=np.add.reduceat(a,indices=0,1,0,2,0,3,0)resultarray(1,2,3,3,6,4,10),if indicesi indicesi+1:resulti=np.reduce(aindicesi:indicesi+1)else:resulti=aindicesi,ufunc的方法,对于indices中的每个元素都会调用reduce函数计算出一个值来,因此最终计算结果的长度和indices的长度相同。结果re

50、sult数组中除最后一个元素之外,都按照如下计算得出:而最后一个元素如下计算:,75,if indicesi indicesi+1:resulti=np.reduce(aindicesi:indicesi+1)else:resulti=aindicesi,np.reduce(aindices-1:),ufunc的方法,因此上面例子中,结果的每个元素如下计算而得:可以看出result:2和a相等,而result1:2和np.add.accumulate(a)相等。,76,1:a0=12:a1=23:a0+a1=1+23:a2=36:a0+a1+a2=1+2+3=64:a3=410:a0+a1+a

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号