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 = (i for i in range(5)) In[18]: a = fromiter(iter, dtype=int32) In[19]: a Out[19]: array([0, 1, 2, 3, 4]) 从函数中生成: In[156]: def f(i, j): ... return abs(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', '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]: for item in array([1, 2, 3, 4]).reshape(2, 2).flat: ... print(item) ... 1 2 3 4 flatiter对象可以直接获取多个元素,并直接赋值修改: 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('1 2 3; 4 5 6; 7 8 9') 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('m I; I m') 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.2 CSV文件读写 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]: def datestr2num(s): return datetime.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]: def f(i): ... return 2*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() for i in range(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() for i in range(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程序设计有所帮助。