Python科学计算包numpy用法实例详解
本文实例讲述了Python科学计算包numpy用法。分享给大家供大家参考,具体如下:
1数据结构
numpy使用一种称为ndarray的类似Matlab的矩阵式数据结构管理数据,比python的列表和标准库的array类更为强大,处理数据更为方便。
1.1数组的生成
在numpy中,生成数组需要指定数据类型,默认是int32,即整数,可以通过dtype参数来指定,一般用到的有int32、bool、float32、uint32、complex,分别代表整数、布尔值、浮点型、无符号整数和复数
一般而言,生成数组的方法有这么几种:
以list列表为参数生成(用tolist方法即可转换回list):
In[3]:a=array([1,2,3]) In[4]:a Out[4]:array([1,2,3]) In[5]:a.tolist() Out[5]:[1,2,3]
指定起点、终点和步长生成等差序列或等比数列:
In[7]:a=arange(1,10,2) In[8]:a Out[8]:array([1,3,5,7,9])
In[13]:a=linspace(0,10,5) In[14]:a Out[14]:array([0.,2.5,5.,7.5,10.])
In[148]:a=logspace(0,3,10)#0表示起点为10^0,3表示起点为10^3,基数通过base参数指定 In[149]:a Out[148]: array([1.,2.15443469,4.64158883,10., 21.5443469,46.41588834,100.,215.443469, 464.15888336,1000.])
从迭代器中生成:
In[17]:iter=(iforiinrange(5)) In[18]:a=fromiter(iter,dtype=int32) In[19]:a Out[19]:array([0,1,2,3,4])
从函数中生成:
In[156]:deff(i,j): ...returnabs(i-j) ... In[157]:fromfunction(f,(4,4)) Out[156]: array([[0.,1.,2.,3.], [1.,0.,1.,2.], [2.,1.,0.,1.], [3.,2.,1.,0.]])
还可以用zeros、ones、empty等函数快速创建数组。
矩阵视为二维数组:
In[24]:b=array([arange(5),arange(1,6),arange(2,7)]) In[25]:b Out[25]: array([[0,1,2,3,4], [1,2,3,4,5], [2,3,4,5,6]])
根据相同的方法可以拓展到更高维。
另外,我们还可以生成自定义数据格式的数组(称为结构数组),用来记录电子表格或数据库中一行数据的信息:
In[61]:t=dtype([('name',str,40),('number',int32),('score',float32)]) In[62]:t Out[62]:dtype([('name','后面我们会看到pandas提供了一种更精致的方法处理记录。
1.2数组的索引
简单的下标索引:
In[30]:a[2] Out[30]:2 In[31]:b[2,1] Out[31]:3与python一样,索引的起点为0。负数的索引当然也是可以的:
In[32]:a[-1] Out[32]:4 In[33]:b[-1,-2] Out[33]:5以整数数组为下标索引,一次性索引多个值:
In[162]:arange(11,20)[array([2,4,8])] Out[161]:array([13,15,19])还可以通过布尔值来索引:
In[40]:idx=array([True,False,False,True,True]) In[41]:a[idx] Out[41]:array([0,3,4])这可以应用在高级索引中,比如条件索引:
b[b>3] Out[42]:array([4,4,5,4,5,6])得到b中所有大于3的元素,以array形式返回,我们能这么写的原因是b>3会返回一个布尔数组,形式与b一致,各位置的值是b中各元素与3比较之后的结果:
In[43]:b>3 Out[43]: array([[False,False,False,False,True], [False,False,False,True,True], [False,False,True,True,True]],dtype=bool)1.3数组的切片
ndarray数组支持各种形式的切片,既可以以下标为线索,还可以以值为线索,为了区分二者,重新生成一个数组:
a=arange(11,20) In[54]:a Out[54]:array([11,12,13,14,15,16,17,18,19])根据下标切片:
In[55]:a[1:4] Out[55]:array([12,13,14]) In[56]:a[1:8:2] Out[56]:array([12,14,16,18]) In[57]:a[1::2] Out[57]:array([12,14,16,18]) In[58]:a[:8:] Out[58]:array([11,12,13,14,15,16,17,18])方括号中三个参数为别是起点、终点和步长,默认值分别是0、-1、1,注意终点是不被包含的。可以简单地令步长为-1来翻转数组:
In[60]:a[::-1] Out[60]:array([19,18,17,16,15,14,13,12,11])ndarray也支持多维数组的切片,先生成一个三维数组,可以通过修改一维数组的shape属性或调用其reshape方法来生成:
In[68]:a=arange(0,24).reshape(2,3,4) In[69]:a Out[69]: 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]]])多维数组的索引其实跟一维区别不大,可以用:代表选取所有:
In[70]:a[:,0,0] Out[70]:array([0,12]) In[71]:a[0,:,0] Out[71]:array([0,4,8]) In[72]:a[0,0,:] Out[72]:array([0,1,2,3]) In[73]:a[0,0:2,0:3] Out[73]: array([[0,1,2], [4,5,6]])多个冒号还可以用...来代替:
In[74]:a[...,3] Out[74]: array([[3,7,11], [15,19,23]])最后,可以使用slice对象来表示切片,它与用1:10:2形式产生切片类似:
In[169]:idx=slice(None,None,2) In[171]:a[idx,idx,idx] Out[170]: array([[[0,2], [8,10]]])相当于a[::2,::2,::2]
1.4数组的变换
可以将上述三维数组展平:
In[75]:a.flatten() Out[75]: 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])转置:
In[77]:b.transpose() Out[77]: array([[0,1,2], [1,2,3], [2,3,4], [3,4,5], [4,5,6]])修改shape属性来改变维度:
In[79]:a.shape=4,6 In[80]:a Out[80]: 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]])1.5数组的组合
首先创建一个与a同大小的数组:
In[83]:b=2*a可以进行多种方式组合,如水平组合:
In[88]:hstack((a,b)) Out[88]: array([[0,1,2,3,4,5,0,2,4,6,8,10], [6,7,8,9,10,11,12,14,16,18,20,22], [12,13,14,15,16,17,24,26,28,30,32,34], [18,19,20,21,22,23,36,38,40,42,44,46]])垂直组合:
In[89]:vstack((a,b)) Out[89]: 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], [0,2,4,6,8,10], [12,14,16,18,20,22], [24,26,28,30,32,34], [36,38,40,42,44,46]])用concatenate函数可以同时实现这两种方式,通过指定axis参数,默认为0,使用垂直组合。
还可以进行深度组合:
In[91]:dstack((a,b)) Out[91]: array([[[0,0], [1,2], [2,4], [3,6], [4,8], [5,10]], [[6,12], [7,14], [8,16], [9,18], [10,20], [11,22]], [[12,24], [13,26], [14,28], [15,30], [16,32], [17,34]], [[18,36], [19,38], [20,40], [21,42], [22,44], [23,46]]])就好像将两张二维平面的点数据沿纵轴方向叠在一起一样。
1.6数组的分割
水平分割:
In[94]:hsplit(a,3) Out[94]: [array([[0,1], [6,7], [12,13], [18,19]]),array([[2,3], [8,9], [14,15], [20,21]]),array([[4,5], [10,11], [16,17], [22,23]])]垂直分割:
In[97]:vsplit(a,2) Out[96]: [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]])]用split函数可以同时实现这两个效果,通过设置其axis参数区别。
类似地,可以通过函数dsplit进行深度分割。
另外可以使用ndarray的一些属性来查看数组的信息:
In[125]:a.ndim#维数 Out[124]:2 In[126]:a.size#元素总个数 Out[125]:24 In[127]:a.itemsize#元素在内存中所占的字节 Out[126]:4 In[128]:a.shape#维度 Out[127]:(4,6) In[130]:a.T#转置,相当于transponse函数 Out[129]: array([[0,6,12,18], [1,7,13,19], [2,8,14,20], [3,9,15,21], [4,10,16,22], [5,11,17,23]],dtype=int32)另外多维数组的flat属性可以给出一个”扁平迭代器“——flatiter对象,使我们能像一维数组一样迭代高维数组:
In[134]:foriteminarray([1,2,3,4]).reshape(2,2).flat: ...print(item) ... 1 2 3 4flatiter对象可以直接获取多个元素,并直接赋值修改:
In[140]:af=a.flat In[141]:af[:] Out[140]: 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],dtype=int32) In[143]:af[3]=15 In[144]:af[:] Out[143]: array([0,1,2,15,4,5,6,7,8,9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23],dtype=int32)1.7矩阵的生成
上面提到了可以用二维数组来模拟矩阵,其实,numpy专门提供了一种用于处理矩阵的数据结构——matrix,它通过mat函数构造生成:
In[8]:m=mat('123;456;789') In[9]:m Out[9]: matrix([[1,2,3], [4,5,6], [7,8,9]])二维数组与矩阵可以很方便地相互转换:
In[11]:array(m) Out[11]: array([[1,2,3], [4,5,6], [7,8,9]]) In[12]:mat(_) Out[12]: matrix([[1,2,3], [4,5,6], [7,8,9]])用matrix来处理矩阵更方便,有更多方法以供使用,如:
求逆:
In[17]:m.I Out[17]: matrix([[-4.50359963e+15,9.00719925e+15,-4.50359963e+15], [9.00719925e+15,-1.80143985e+16,9.00719925e+15], [-4.50359963e+15,9.00719925e+15,-4.50359963e+15]])分块矩阵:
In[25]:I=eye(3) In[26]:bmat('mI;Im') Out[26]: matrix([[1.,2.,3.,1.,0.,0.], [4.,5.,6.,0.,1.,0.], [7.,8.,9.,0.,0.,1.], [1.,0.,0.,1.,2.,3.], [0.,1.,0.,4.,5.,6.], [0.,0.,1.,7.,8.,9.]])2数据处理
2.1条件判断和搜索
用where函数可以得到满足条件的索引,便于后期处理:
In[219]:a=arange(24).reshape(4,6) In[220]:where(a>8) Out[219]: (array([1,1,1,2,2,2,2,2,2,3,3,3,3,3,3],dtype=int32), array([3,4,5,0,1,2,3,4,5,0,1,2,3,4,5],dtype=int32))用compress函数可以筛选出一维数组中满足条件的值:
In[28]:a[0,:].compress(a[0,:]>2) Out[28]:array([3,4,5])2.2CSV文件读写
CSV(逗号分割值)格式可以简单方便地保存数组或矩阵。相比于python的pickle方法,保存为CSV文件可以用一般文本编辑器随时打开查看。保存和读取CSV文件都很简单。
In[190]:b Out[189]: array([[0,2,4,6,8,10], [12,14,16,18,20,22], [24,26,28,30,32,34], [36,38,40,42,44,46]]) In[191]:savetxt("b.txt",b,delimiter=",") In[192]:b1,b2=loadtxt("b.txt",delimiter=",",usecols=(3,4),unpack=True) In[193]:b1,b2 Out[192]:(array([6.,18.,30.,42.]),array([8.,20.,32.,44.]))保存时参数delimiter可选,用来分隔数组各元素,读取时也要相应地指定这个值,读取时也可只读取部分数据,usecols即用来指定选取的列,unpack设置为True时表示将这些列分开存储。
读写时遇到字符串(如时间)可以通过指定参数converters来转换。
In[252]: defdatestr2num(s): returndatetime.datetime.strptime(str(s,encoding="utf-8"),"%Y-%m-%d").date().weekday() weeks,numbers=loadtxt("b.txt",converters={0:datestr2num},unpack=True) In[253]:weeks Out[252]:array([2.,4.])2.3通用函数
用frompyfunc函数可以将一个作用在单一数值的函数映射到作用在数组上的函数:
In[49]:deff(i): ...return2*i ... In[50]:ff=frompyfunc(f,1,1) In[52]:ff(a) Out[52]: array([[0,2,4,6,8,10], [12,14,16,18,20,22], [24,26,28,30,32,34], [36,38,40,42,44,46]],dtype=object)frompyfunc的两个参数分别定义输入参数和输出参数的个数
另外,numpy提供了一些常用的通用函数,如针对加减乘除的add、subtract、multiply和divide。通用函数都有四个方法:reduce、accumulate、reduceat和outer,以add函数为例:
In[64]:add.reduce(a[0,:]) Out[64]:15 In[65]:add.accumulate(a[0,:]) Out[65]:array([0,1,3,6,10,15],dtype=int32) In[69]:add.reduceat(a[0,:],[0,5,2,4]) Out[69]:array([10,5,5,9],dtype=int32) In[70]:add.outer(a[0,:],a[1,:]) Out[70]: array([[6,7,8,9,10,11], [7,8,9,10,11,12], [8,9,10,11,12,13], [9,10,11,12,13,14], [10,11,12,13,14,15], [11,12,13,14,15,16]])可见,reduce是将通用函数递归作用在所有元素上,得到最后结果;accumulate也是递归作用在所有元素上,不过它保留中间结果并返回;reduceat则根据指定的起始点进行累积运算,如果终点小于起点,则返回终点处的值;最后outer则是对两个输入数组的所有元素组合进行运算。
3科学计算
3.1统计分析
3.1.1基本统计分析
average函数可以非常方便地计算加权平均值,或者用mean计算算术平均值:
In[204]:a=array([1,2]) In[205]:average(a,weights=[1,2]) Out[204]:1.6666666666666667基本统计分析函数整理如下:
中位数:median
方差:var
标准差:std
差分:diff
最值:max、min、argmax、argmin(后两个得到最值所在的下标)3.1.2随机过程分析
3.2线性代数
先生成一个各元素是0~1之内的随机数的矩阵:
In[47]:a=mat(fromiter((random.random()foriinrange(9)),dtype=float32).reshape(3,3)) In[48]:a Out[48]: matrix([[0.45035544,0.53587919,0.57240343], [0.54386997,0.16267321,0.97020519], [0.6454953,0.38505632,0.94705021]],dtype=float32)接下我们可以对它进行各种线性代数的操作,如:
求逆:
In[49]:a.I Out[49]: matrix([[-10.71426678,-14.01229095,20.83065987], [5.42686558,2.7832334,-6.13131571], [5.09620285,8.41894722,-10.64905548]],dtype=float32)解线性方程组(用点积验证了结果):
In[59]:b=fromiter((random.random()foriinrange(3)),dtype=float32) In[60]:b Out[60]:array([0.56506187,0.99419129,0.70462942],dtype=float32) In[61]:linalg.solve(a,b) Out[61]:array([-5.3072257,1.51327574,3.74607611],dtype=float32) In[63]:dot(a,_) Out[63]:matrix([[0.56506193,0.99419105,0.70462948]],dtype=float32)求特征值和特征向量:
In[64]:linalg.eig(a) Out[64]: (array([1.78036737,-0.08517434,-0.13511421],dtype=float32), matrix([[-0.5075314,-0.82206506,0.77804375], [-0.56222379,0.4528676,-0.57155234], [-0.65292901,0.34513769,-0.26072171]],dtype=float32))行列式:
In[81]:linalg.det(a) Out[81]:0.020488938更多关于Python相关内容感兴趣的读者可查看本站专题:《Python数学运算技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》
希望本文所述对大家Python程序设计有所帮助。