Python科学计算包numpy用法实例详解


Posted in Python onFebruary 08, 2018

本文实例讲述了Python科学计算包numpy用法。分享给大家供大家参考,具体如下:

1 数据结构

numpy使用一种称为ndarray的类似Matlab的矩阵式数据结构管理数据,比python的列表和标准库的array类更为强大,处理数据更为方便。

1.1 数组的生成

在numpy中,生成数组需要指定数据类型,默认是int32,即整数,可以通过dtype参数来指定,一般用到的有int32boolfloat32uint32complex,分别代表整数、布尔值、浮点型、无符号整数和复数

一般而言,生成数组的方法有这么几种:

以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', '<U40'), ('number', '<i4'), ('score', '<f4')])
In[63]: students = array([('Tom', 10, 80), ('Jenny', 11, 90.5), ('Mike', 9, 98.5)], dtype=t)
In[64]: students
Out[64]: 
array([('Tom', 10, 80.0), ('Jenny', 11, 90.5), ('Mike', 9, 98.5)], 
   dtype=[('name', '<U40'), ('number', '<i4'), ('score', '<f4')])
In[65]: students[1]
Out[65]: ('Jenny', 11, 90.5)

后面我们会看到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]: 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
最值maxminargmaxargmin(后两个得到最值所在的下标)

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中if __name__ == &quot;__main__&quot;详细解释
Oct 21 Python
python实现从ftp服务器下载文件的方法
Apr 30 Python
Python中类的初始化特殊方法
Dec 01 Python
基于numpy.random.randn()与rand()的区别详解
Apr 17 Python
Python检查ping终端的方法
Jan 26 Python
python 对字典按照value进行排序的方法
May 09 Python
pyqt5让图片自适应QLabel大小上以及移除已显示的图片方法
Jun 21 Python
ERLANG和PYTHON互通实现过程详解
Jul 05 Python
解决Django no such table: django_session的问题
Apr 07 Python
一文读懂Python 枚举
Aug 25 Python
python 对象真假值的实例(哪些视为False)
Dec 11 Python
Python超简单容易上手的画图工具库推荐
May 10 Python
Python多进程并发与多线程并发编程实例总结
Feb 08 #Python
Python的CGIHTTPServer交互实现详解
Feb 08 #Python
Python获取CPU、内存使用率以及网络使用状态代码
Feb 08 #Python
python实现二叉查找树实例代码
Feb 08 #Python
单链表反转python实现代码示例
Feb 08 #Python
Python测试人员需要掌握的知识
Feb 08 #Python
python实现单向链表详解
Feb 08 #Python
You might like
索尼SONY ICF-SW7600GR电路分析与改良
2021/03/02 无线电
PHP 获取远程网页内容的代码(fopen,curl已测)
2011/06/06 PHP
一些php项目中比较通用的php自建函数的详解
2013/06/06 PHP
解析PHP将对象转换成数组的方法(兼容多维数组类型)
2013/06/21 PHP
网页上facebook分享功能具体实现
2014/01/26 PHP
php 解压rar文件及zip文件的方法
2014/05/05 PHP
PHP判断一个数组是另一个数组子集的方法详解
2017/07/31 PHP
PHP中define() 与 const定义常量的区别详解
2019/06/25 PHP
javascript SocialHistory 检查访问者是否访问过某站点
2008/08/02 Javascript
javascript window对象属性整理
2009/10/24 Javascript
获取焦点时,利用js定时器设定时间执行动作
2010/04/02 Javascript
node.js chat程序如何实现Ajax long-polling长链接刷新模式
2012/03/13 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
2013/10/11 Javascript
jQuery实现带滚动导航效果的全屏滚动相册实例
2015/06/19 Javascript
Bootstrap入门书籍之(四)菜单、按钮及导航
2016/02/17 Javascript
JavaScript驾驭网页-CSS与DOM
2016/03/24 Javascript
jQuery插件实现图片轮播特效
2016/06/16 Javascript
必备的JS调试技巧汇总
2016/07/20 Javascript
jQuery焦点图左右转换效果
2016/12/12 Javascript
vue刷新和tab切换实例
2018/02/11 Javascript
nodejs搭建本地服务器轻松解决跨域问题
2018/03/21 NodeJs
vue实现todolist功能、todolist组件拆分及todolist的删除功能
2019/04/11 Javascript
vue路由守卫+登录态管理实例分析
2019/05/21 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
Python 常用string函数详解
2016/05/30 Python
Python实现信用卡系统(支持购物、转账、存取钱)
2016/06/24 Python
在python3.5中使用OpenCV的实例讲解
2018/04/02 Python
python射线法判断一个点在图形区域内外
2019/06/28 Python
Python暴力破解Mysql数据的示例
2020/11/09 Python
专门出售各种儿童读物的网站:Put Me In The Story
2016/08/07 全球购物
美国在线家装零售商:Build.com
2016/09/02 全球购物
保时捷设计:Porsche Design
2019/03/30 全球购物
迪斯尼假期(欧洲、中东及非洲):Disney Holidays EMEA
2021/02/15 全球购物
如何通过jdbc调用存储过程
2012/04/19 面试题
先进党支部事迹材料
2014/01/13 职场文书
于丹讲座视频观后感
2015/06/15 职场文书