流畅的 Python(33):序列构成的数组 2.9.3

阅读数:12 2019 年 11 月 20 日 17:15

流畅的Python(33):序列构成的数组 2.9.3

内容简介
本书致力于帮助 Python 开发人员挖掘这门语言及相关程序库的优秀特性,避免重复劳动,同时写出简洁、流畅、易读、易维护,并且具有地道 Python 风格的代码。本书尤其深入探讨了 Python 语言的高级用法,涵盖数据结构、Python 风格的对象、并行与并发,以及元编程等不同的方面。

(NumPy 和 SciPy)

整本书我都在强调如何最大限度地利用 Python 标准库。但是 NumPy 和 SciPy 的优秀让我觉得偶尔跑个题来谈谈它们也是很值得的。

凭借着 NumPy 和 SciPy 提供的高阶数组和矩阵操作,Python 成为科学计算应用的主流语言。NumPy 实现了多维同质数组(homogeneous array)和矩阵,这些数据结构不但能处理数字,还能存放其他由用户定义的记录。通过 NumPy,用户能对这些数据结构里的元素进行高效的操作。

SciPy 是基于 NumPy 的另一个库,它提供了很多跟科学计算有关的算法,专为线性代数、数值积分和统计学而设计。SciPy 的高效和可靠性归功于其背后的 C 和 Fortran 代码,而这些跟计算有关的部分都源自于 Netlib 库。换句话说,SciPy 把基于 C 和 Fortran 的工业级数学计算功能用交互式且高度抽象的 Python 包装起来,让科学家如鱼得水。

示例 2-22 是一个很简短的演示,从中可以窥见一些 NumPy 二维数组的基本操作。

示例 2-22 对 numpy.ndarray 的行和列进行基本操作

>>> import numpy  ➊
>>> a = numpy.arange(12)  ➋
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,  11])
>>> type(a)
<class 'numpy.ndarray'>
>>> a.shape  ➌
(12,)
>>> a.shape = 3, 4  ➍
>>> a
array([[  0,  1,  2,  3],
       [  4,  5,  6,  7],
       [  8,  9, 10, 11]])
>>> a[2]  ➎
array([  8,  9,  10,  11])
>>> a[2, 1]  ➏
9
>>> a[:, 1]  ➐
array([1, 5, 9])
>>> a.transpose() ➑
array([[  0,  4,  8],
       [  1,  5,  9],
       [  2,  6, 10],
       [  3,  7, 11]])

❶ 安装 NumPy 之后,导入它(NumPy 并不是 Python 标准库的一部分)。

❷ 新建一个 0~11 的整数的 numpy.ndarry,然后把它打印出来。

❸ 看看数组的维度,它是一个一维的、有 12 个元素的数组。

❹ 把数组变成二维的,然后把它打印出来看看。

❺ 打印出第 2 行。

❻ 打印第 2 行第 1 列的元素。

❼ 把第 1 列打印出来。

❽ 把行和列交换,就得到了一个新数组。

NumPy 也可以对 numpy.ndarray 中的元素进行抽象的读取、保存和其他操作:

>>> import numpy
>>> floats = numpy.loadtxt('floats-10M-lines.txt')  ➊
>>> floats[-3:]  ➋
array([ 3016362.69195522, 535281.10514262, 4566560.44373946])
>>> floats *= .5  ➌
>>> floats[-3:]
array([ 1508181.34597761, 267640.55257131, 2283280.22186973])
>>> from time import perf_counter as pc  ➍
>>> t0 = pc(); floats /= 3; pc() - t0  ➎
0.03690556302899495
>>> numpy.save('floats-10M', floats)  ➏
>>> floats2 = numpy.load('floats-10M.npy', 'r+')  ➐
>>> floats2 *= 6
>>> floats2[-3:]  ➑
memmap([3016362.69195522, 535281.10514262, 4566560.44373946])

❶ 从文本文件里读取 1000 万个浮点数。

❷ 利用序列切片来读取其中的最后 3 个数。

❸ 把数组里的每个数都乘以 0.5,然后再看看最后 3 个数。

❹ 导入精度和性能都比较高的计时器(Python 3.3 及更新的版本中都有这个库)。

❺ 把每个元素都除以 3,可以看到处理 1000 万个浮点数所需的时间还不足 40 毫秒。

❻ 把数组存入后缀为 .npy 的二进制文件。

❼ 将上面的数据导入到另外一个数组里,这次 load 方法利用了一种叫作内存映射的机制,它让我们在内存不足的情况下仍然可以对数组做切片。

❽ 把数组里每个数乘以 6 之后,再检视一下数组的最后 3 个数。

NumPy 和 SciPy 的安装可能会比较费劲。在“ Installing the SciPy Stack ”页面,SciPy.org 建议找一个科学计算 Python 的分发渠道帮忙,比如 Anacoda、Enthought Canopy、WinPython,等等。常见的 GNU/Linux 版本的用户应该可以在他们自己的包管理系统中找到 NumPy 和 SciPy。例如,在 Debian 或者 Ubuntu 上面,用户可以通过下面的命令一键安装:

$ sudo apt-get install python-numpy python-scipy

以上的内容仅仅是九牛一毛。NumPy 和 SciPy 都是异常强大的库,也是其他一些很有用的工具的基石。 Pandas Blaze 数据分析库就以它们为基础,提供了高效的且能存储非数值类数据的数组类型,和读写常见数据文件格式(例如 csv、xls、SQL 转储和 HDF5)的功能。因此,要详细介绍 NumPy 和 SciPy 的话,不写成几本书是不可能的。虽然本书不在此列,但是如果要对 Python 的序列类型做一个概览,恐怕没有人能忽略 NumPy。

在介绍完扁平序列(包括标准数组和 NumPy 数组)之后,让我们把目光投向 Python 中可以取代列表的另外一种数据结构:队列。

图灵地址 https://www.ituring.com.cn/book/1564

评论

发布