numpy简明教程(3)

来源:互联网 发布:扫描仪软件下载 编辑:程序博客网 时间:2024/06/05 09:05

《用Python做科学计算》做得很漂亮,字体瞧着顺眼儿,代码部分不仅照例是等宽字符,还换了灰背景,作者是个有心人。今天答辩委员会的专家还提到了写论文要细致严谨,除了文字之外的其他细节包括图表的刻度、图例和图注还有论文字体大小对齐等等都要力争做到至少规范。因此在投入程度方面儿我要向作者致敬并学习。当然,还有他/她的开源精神~

从目录看只准备看NumPy,SciPy和matplotlib的部分。此外比较感兴趣的是3D演示方面的,因为之前没怎么接触过,不过那部分等先学biopython和wxPython、然后继续修炼一阵Python再说,现在还远照顾不到。吾生也有涯!

凡例:a. [float]表示对象类型是float,用时不用加'['和']'。

Chap 2 NumPy-快速处理数据


1. 两个科学计算Python合集:Python(x,y)和Enthought Python Distribution (EPD)。交互解释器:iPython(装了一个,偶尔用用,还没体会到比Python自带的shell的强大所在及程度)、spyder(Python(x,y)自带的IDE,模仿MATLAB的workspace功能)。比较有用的函数库:Numpy,SciPy,SymPy(符号运算系虾米?),Traits(界面设计库,说得我都想弃wxPython开始学这个了。在计算机领域学什么是个很重要的问题。),TVTK(用Traits库封装的标准VTK库),Visual(制作3D动画演示),OpenCV(这个前几天还碰到过,感觉跟图像生成渲染之类的有关,对于Python,也提供了API)。


2. 调整shape时数组(就是官方文档里的array)元素在内存中的位置并没有改变,也就是提供了一种view而非copy。如果某一维数值是-1,则按数组的长度和其他维度的数值自动计算。


3. reshape方法也是,返回一个shape修改过的数组,但是还是view而非copy。


4. 和linspace相似,logspace创建在log尺度均匀分布的数值组成的数列,即等比数列。


5. 此外,还可以使用frombuffer, fromstring, fromfile等函数可以从字节序列创建数组,也就是上次没有深入的领域。以fromstring为例,在内存中以字节方式存储。一个字节(byte)占8个bit(终于搞明白byte和bit的关系啦,呼瑞!),如果要转化成int16的话有个两个字节串联顺序的问题。Python里是以little endian(又见little endian!当年写tiqho的时候没整明白的问题终于搞明白了,happy)方式在内存中保存数据的,即低位字节在前,故int16值等于之前的字节*256(应该是因为是一个byte占8个bit,故用2^8,不过还是没彻底明白)加上后一个字节。


6. 还可以使用fromfunction利用自己写的函数进行转换。比如:np.fromfunction(func, (10,)),其中func是自写函数,(10,)是返回数组的shape。func的参数默认从0开始,直到填满指定的shape。


7. 数组的reference还可以用boolean array(一般不是手动一个个敲出来的,见
9),此时必须是array,不能再用列表蒙混了,broadcast时都按False算。返回其中为True的元素的相应位置上的目标array中的元素。


8. np.random.rand([int]) :产生一个长度为[int],元素值为0-1的随机数的数组。


9. 对于数组,如果进行大小比较,和Python里类似,返回的也是bool,不过是个数组。这个数组就可以用来做7里的reference。见7。


10. seriously?——“组元不需要圆括号虽然我们经常在Python中用圆括号将组元括起来,但是其实组元的语法定义只需要用逗号隔开即可。


11. 结构数组(structured array)有点像类(或者我理解的类),定义一个dtype对象,有一定模式,然后指定其他对象的dtype是它。


12. 查看dtype:obj.dtype,可能返回如下:dtype([('name', '|S32'), ('age', '<i4'), ('weight', '<f4')]),其中“|”, “<”等字符,这些字符用来描述字段值的字节顺序:“|”:忽视字节顺序,“<”:little endian,“>”:big endian。


13. 作者认为“在C语言中我们可以通过struct关键字定义结构类型,结构中的字段占据连续的内存空间,每个结构体占用的内存大小都相同”。受教了。


14. 通过调用数组的tostring或者tofile方法,可以直接输出数组的二进制形式。比如:a.tofile("test.bin")。


15. 和C语言协作使用时需要注意的是C语言的结构体为了内存寻址方便,会自动的添加一些填充用的字节,即内存对齐,以保持最终的结构体大小变。因此如果NumPy中的所配置的内存大小不符合C语言的对齐规范的话,将会出现数据错位。在创建dtype对象时,可以传递参数align=True以确保不发生数据错位。


16. 用字典参数也可以定义dtype对象时,因为字典的关键字是没有顺序的,所以需要在类型描述中给出字段的顺序。用法是在字段(field)后给出偏移量(即offset)的值,单位是byte,如:dtype([('surname', '|S25'), ('age', '|u1')])。


17. ndarray在内存中的数据结构太深,不过为了将来万一和其他语言的串接,硬着头皮看一看吧。ndarray数据结构引用两个对象:数据存储区和dtype对象存储区,具体包括dtype,dim count,dimensions,strides和data。dim count指维度的数目;dimesion指各维度的数字;strides指每个轴的下标增加1时数据存储区中的指针所增加的字节数,比如有个3*3的数组,元素类型是float32,那么每个数占4(32/8)字节。在C语言格式中,第二个维度的数字比第一个变得快,所以第二个维度数字增加1指针增加4字节,第一个的话就是12(4*3)个字节,所以strides(本身就有步伐”的意思)分别为12和4。不过这要求数据在内存中连续存储。另一种数字跳的方式是Fortran语言格式的,需要重设参数值,改变默认设定:order=''F''。


18. ufunc原来是说能对数组里每个元素都操作的函数,ft~


19. ufunc创建新数组并返回,如果要覆盖的话可以在第二个参数里指定被覆盖的对象,比如:t = np.sin(x,x),x表现为经过了更新。


20. 算数计算运算符和函数,其中[, y]是可选参数,用于指定覆盖对象,除号运算符的处理根据是否激活__future__.division有所不同:x1+x2,相当于add(x1, x2 [, y]);x1-x2,相当于subtract(x1, x2 [, y]);x1*x2,multiply(x1, x2 [, y]);x1/x2: divide(x1, x2 [, y]),整数除法;x1/x2: true divide (x1, x2 [, y]), 返回精确的商;x1//x2,floor divide (x1, x2 [, y]),地板除;-x,negative(x [,y]);x1**x2,power(x1, x2 [, y]);x1%x2,remainder(x1, x2 [, y]), mod(x1, x2, [, y])。


21. 复杂的算式处理大数组会产生大量的中间结果而导致速度减缓,一个小技巧是手工拆分算式分解,以尽量减少内存分配,提高速度。


22. 下一个是应该算是神器级别的函数:frompyfunc,把Python里的函数(可以是自写的)转化成ufunc,用法是frompyfunc(func, nin, nout),其中func是需要转换的函数,nin是函数的输入参数的个数,nout是此函数的返回值的个数。注意frompyfunc函数无法保证返回的数据类型都完全一致,因此返回一个中间类型object,需要再次obj.astype(np.float64)之类将其元素类型强制调齐。


23. 作者对broadcast的处理是直接翻成“广播”。补齐的规则除了以前记下的,还有:维度差异的部分通过在已有的维度前面加1进行补齐;输出数组的shape是输入数组shape的各个轴上的最大值;当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值。


24. repeat方法:b.repeat(6,axis=0),在第0轴(shape里的第一个维度)的方向上长度扩展为6,也就是第2个维度重复5次(有点绕,呵呵)。


25. ogrid对象:用切片组元作为下标进行存取,返回一到多个可以用来广播计算的数组。有两种用法:开始值:结束值:步长,和np.arange类似(不包含结束值喽); 开始值:结束值:长度j,当第三个参数为虚数时,它表示返回的数组的长度,和np.linspace类似(包含结束值)。


26. ufunc的reduce 方法:和Python的reduce函数类似,沿着一个指定的轴将运算符插入这根轴上所有子数组或者元素当中,并返回结果,比如:np.add.reduce([[1,2,3],[4,5,6]], axis=1),其中axis为1,指的是第2个维度上的元素,即[1,2,3]和[4,5,6]。


27. accumulate与reduce类似,不同之处在于返回的数组里包括所有中间结果,致使其shape与输入数组的相同。比如:np.add.accumulate([[1,2,3],[4,5,6]], axis=1),返回array([[1,3,6],[4,9,15]]),其中1(1),3(1+2),4(4),9(4+5)是中间结果。


28. reduceat方法通过indices参数(列表形式)指定一系列插入reduce的起始和终止位置(reduce at嘛),规则如下:如果indice中某元素小于其后元素,则相应结果为对以这两个元素为位置产生的slice里的数组元素进行reduce;否则结果是这个元素对应的数组元素。对于最后一个元素,因为其后再没元素,结果为对所有元素进行reduce。例子:np.add.reduceat(np.array([1,2,3,4]),indices=[0,1,0,2,0,3,0]),返回array([1,2,3,3,6,4,10])。


29. outer方法,<op>.outer(a,b)方法的计算等同于如下程序:a.shape += (1,)*b.ndim    <op>(a,b)    a = a.squeeze()。例子:np.multiply.outer([1,2,3,4,5],[2,3,4])。在这个例子中,首先,a.shape += (1,)*1,即a.shape变成了(5,1),然后multiply(a,b),然后,a = a.squeeze()剔除数组a中长度为1的轴,也就是恢复a的shape,把a给还原了。


30. 终于进入矩阵部分了,NumPy和Matlab不一样,对于多维数组的运算,缺省情况下并不使用矩阵运算。但因为NumPy中同时存在ndarray和matrix类,用户很容易将两者弄混,有违the Zen of Python(import this!),因此matrix类的优先状态是不启用。


31. 矩阵乘法:如果需要将一维数组当作列矢量或者行矢量进行矩阵运算时,推荐先reshape之。


32. dot函数:对于一维数组,计算内积,就是两个数组对应下标元素的乘积(应该就是点积);对于二维数组计算矩阵乘积(嘛意思?);对于更高维数组,规则是:dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m]),即结果数组中的每个元素都是数组a的最后一维上的所有元素与数组b的倒数第二维上的所有元素的乘积之和。


33. np.alltrue(),check是否数组每个元素均为True。


34. inner : 对于两个一维数组计算内积;对于多维数组,它计算的结果数组中的每个元素都是:数组a和b的最后一维的内积,因此数组a和b的最后一维的长度必须相同,即:inner(a, b)[i,j,k,m] = sum(a[i,j,:]*b[k,m,:])。


35. outer : 只按照一维数组进行计算,如果传入参数是多维数组,则先将此数组展平为一维数组之后再进行运算,结果是列向量和行向量的矩阵乘积。感觉跟multiply.outer没啥区别啊,见29。


36. np.linalg库还有很多线性代数领域的函数和功能,比如以前用过的np.linalg.det。这本书里提到了可求逆矩阵的inv函数,和求解多元一次方程组的solve函数。后者用法:np.linalg.solve(a,b),其中a是一个N*N的二维数组,而b是一个长度为N的一维数组,solve函数找到一个长度为N的一维数组x,使得a和x的矩阵乘积正好等于b,数组x就是多元一次方程组的解。


37. 现在进入文件存取了。使用tofile可以方便地将数组中数据以二进制的格式写进文件。tofile输出的数据不带格式,shape和dtype都没有,且使用C语言格式输出,不管数组本身的格式。因此,用fromfile读回来的时候需要自己格式化数据。


38. tofile方法还可以输出为文本格式,此时需要指定sep参数。用fromfile读取时也需要指定此参数。


39. 较为方便的方法是用load和save函数进行数据存取,文件名后缀是.npy,格式是NumPy专用的二进制类型,不用再管shape和dtype这些,不过代价是很难与其他语言的程序协作。通用和专有的矛盾!


40. savez:多个数组保存在同一文件中,第一个参数是输出文件名,后面是其后的参数都是需要保存的数组,自动起名为arr_0, arr_1, ...,也可以使用关键字参数为数组起一个名字。输出文件扩展名为.npz,是一个压缩包,其中每个文件都是.npy,内含一个数组,文件名即内涵数组名。


41. 对于.npz文件,load函数自动识别并且返回一个类似于字典的对象,可以通过数组名作为关键字获取数组的内容。


42. savetxt和loadtxt分别存取txt文件,与tofile不同的是数字此时不是以二进制的方式保存的。用法:np.savetxt("a.txt", a, fmt="%d", delimiter=","),fmt默认为'%.18e',delimiter默认为' '。显然如果以非默认设置输出了读取时也要修改相应参数。


43. load和save函数还可以对已经打开的文件对象进行操作,比如:f = file("result.npy", "wb")    np.save(f, a)    f.close(),其中a是一个数组。读取时也是先定义一个句柄f,然后多次np.load(f),可以顺序(save时的顺序)读取数组。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 和公婆住一起很压抑怎么办 不想和公婆一起住怎么办 在家啃老三年了怎么办 新时代卫计工作怎么办 被公司辞退不发工资怎么办 被公司辞退后不发工资怎么办 领导分配的工作太多怎么办 领导故意不给活怎么办 户口迁移后医疗社保怎么办 有了c证考b证怎么办 顶替姐姐上班已到退休年龄怎么办 年龄过60岁厂里拖欠工资怎么办 领导找人顶替我怎么办 宁夏超生了没钱交罚款怎么办? 户口年龄上大了怎么办 孩子年龄报小了怎么办 招工档案年龄有涂改怎么办 退伍军被别人顶替上班怎么办 二孩政策前生的怎么办 孩子晕车怎么办最有效方法得当 事业单位编外人员改革工伤怎么办 工伤仲裁后法院一审判决后怎么办 我媳妇删了我该怎么办 老婆离家出走不照顾小孩怎么办 车停在4s店损坏怎么办 车辆年检贴丢了怎么办 卖衣服别人嫌贵怎么办 武汉铁路医保卡丢了怎么办 高铁列车员年龄大了怎么办 尚客优酒店会员怎么办 钢铁雄心4人力不足怎么办 未经车主同意私自将车卖了怎么办 剧本给几个制片人看过怎么办 没有产品经理ui设计师怎么办 老板请朋友吃饭司机应该怎么办 被化妆学校坑了怎么办 快车约得太远怎么办 工资好低2000多怎么办 苹果手机不能下载软件怎么办 苹果手机下不了软件怎么办 苹果6s下不了软件怎么办