如果不懂 numpy,请别说自己是 python 程序员

如果不懂 numpy,请别说自己是 python 程序员

如果不懂 numpy,请别说自己是 python 程序员

关注我你就是我的人了

大约七八年前,我曾经用 pyOpenGL 画过地球磁层顶的三维模型,这段代码至今仍然还运行在某科研机构里。在那之前,我一直觉得自己是一个合(you)格(xiu)的 python 程序员,似乎无所不能。但磁层顶模型的显示效果令我沮丧——尽管这个模型只有十几万个顶点,拖拽、缩放却非常卡顿。最终,我把顶点数量删减到两万左右,以兼顾模型质量和响应速度,才勉强交付了这个任务。从此我开始怀疑 python 的性能,甚至一度怀疑 python 是否还是我的首选工具。

幸运的是,后来我遇到了 numpy 这个神器。numpy 是 python 科学计算的基础软件包,提供多了维数组对象,多种派生对象(掩码数组、矩阵等)以及用于快速操作数组的函数及 API,它包括数学、逻辑、数组形状变换、排序、选择、I/O 、离散傅立叶变换、基本线性代数、基本统计运算、随机模拟等等。

了解 numpy之后,我才想明白当初磁层顶的三维模型之所以慢,是因为使用了 list(python 数组)而不是 ndarray(numpy 数组)存储数据。有了 numpy,python 程序员才有可能写出媲美 C 语言运行速度的代码。熟悉 numpy,才能学会使用 pyOpenGL / pyOpenCV / pandas / matplotlib 等数据处理及可视化的模块。

事实上,numpy 的数据组织结构,尤其是数组(numpy.ndarray),几乎已经成为所有数据处理与可视化模块的标准数据结构了(这一点,类似于在机器学习领域 python 几乎已经成为首选工具语言)。越来越多的基于 python 的科学和数学软件包使用 numpy 数组,虽然这些工具通常都支持 python 的原生数组作为参数,但它们在处理之前会还是会将输入的数组转换为 numpy 的数组,而且也通常输出为 numpy 数组。在 python 的圈子里,numpy 的重要性和普遍性日趋增强。换句话说,为了高效地使用当今科学/数学基于 python 的工具(大部分的科学计算工具),你只知道如何使用 python 的原生数组类型是不够的,还需要知道如何使用 numpy 数组。

总结:在这个 AI 和 ML 霸屏的时代,如果不懂 numpy,请别说自己是 python 程序员。


如果不懂 numpy,请别说自己是 python 程序员

1. list VS ndarray

numpy 的核心是 ndarray 对象(numpy 数组),它封装了 python 原生的同数据类型的 n 维数组(python 数组)。numpy 数组和 python 数组之间有几个重要的区别:

然而,以上的差异并没有真正体现出 ndarray 的优势之所在,ndarray 的精髓在于 numpy 的两大特征:矢量化(vectorization)和广播(broadcast)。矢量化可以理解为代码中没有显式的循环、索引等,广播可以理解为隐式地对每个元素实施操作。矢量化和广播理解起来有点抽象,我们还是举个栗子来说明一下吧。

**例题 ** a 和 b 是等长的两个整数数组,求 a 和 b 对应元素之积组成的数组。

1.用 python 数组实现:

用 numpy 数组实现:

这个栗子是不是体现了矢量化和广播的强大力量呢?请仔细体会!

总结:


如果不懂 numpy,请别说自己是 python 程序员

2. dtype AND shape

子曰:找对象先了解品行,学对象先了解属性。 ndarray 对象有很多属性,详见下表。

属性 说明

ndarray.dtype元素类型

ndarray.shape数组的结构

ndarray.ndim秩,即轴的数量或维度的数量

ndarray.size数组元素的个数

ndarray.itemsize每个元素的大小,以字节为单位

ndarray.flags数组的内存信息

ndarray.real元素的实部

ndarray.imag元素的虚部

ndarray.data数组元素的实际存储区

基于以下三个原因,我认为,dtype 和 shape 是 ndarray 最重要的两个属性,重要到几乎可以忽略其他的属性。

ndarray.astype() 可以修改元素类型, ndarray.reshape() 可以重新定义数组的结构,这两个方法的重要性和其对应的属性一样。记住这两个属性和对应的两个方法,就算是登堂入室了。想了解 numpy 支持的元素类型,请点击《数学建模三剑客MSN》

3. 创建数组

(1) 创建简单数组

应用示例:

(2) 创建随机数组

应用示例:

(3) 在数值范围内创建数组

应用示例:

(4) 从已有数组创建数组

应用示例:

(5) 构造复杂数组

[1] 重复数组 tile

[2] 重复元素 repeat

[3] 一维数组网格化: meshgrid

[4] 指定范围和分割方式的网格化: mgrid

上面的例子中用到了虚数。构造复数的方法如下:

假设有一栋2层楼,每层楼内的房间都是3行4列,那我们可以用一个三维数组来保存每个房间的居住人数(当然,也可以是房间面积等其他数值信息)。

提示:对多维数组切片或索引得到的结果,维度不是确定的。

(2) 改变数组的结构

np.rollaxis() 用于改变轴的顺序,返回一个新的数组。用法如下:

a: 数组

应用示例:

(3) 数组合并

[1] append

对于刚刚上手 numpy 的程序员来说,最大的困惑就是不能使用 append() 方法向数组内添加元素了,甚至连 append() 方法都找不到了。其实,numpy 仍然保留了 append() 方法,只不过这个方法不再是 numpy 数组的方法,而是是升级到最外层的 numpy 命名空间了,并且该方法的功能不再是追加元素,而是合并数组了。

[2] concatenate

concatenate() 和 append() 的用法非常类似,不过是把两个合并对象写成了一个元组 。

[3] stack

除了 append() 和 concatenate() ,数组合并还有更直接的水平合并(hstack)、垂直合并(vstack)、深度合并(dstack)等方式。假如你比我还懒,那就只用 stack 吧,足够了。

(4) 数组拆分

拆分是合并的逆过程,概念是一样的,但稍微有一点不同:

(5) 数组排序

排序不是 numpy 数组的强项,但 python 数组的排序速度依然只能望其项背。

[1] numpy.sort()

numpy.sort() 函数返回输入数组的排序副本。

应用示例:

[2] numpy.argsort()

函数返回的是数组值从小到大的索引值。

应用示例:

(6) 查找和筛选

[1] 返回数组中最大值和最小值的索引

[2] 返回数组中非零元素的索引

[3] 返回数组中满足给定条件的元素的索引

应用示例:

[4] 返回数组中被同结构布尔数组选中的各元素

应用示例:

(7) 增减元素

[1] 在给定索引之前沿给定轴在输入数组中插入值,并返回新的数组

应用示例:

[2] 在给定索引之前沿给定轴删除指定子数组,并返回新的数组

应用示例:

[3] 去除重复元素

应用示例:

(8) 数组IO

numpy 为 ndarray 对象引入了新的二进制文件格式,用于存储重建 ndarray 所需的数据、图形、dtype 和其他信息。.npy 文件存储单个数组,.npz 文件存取多个数组。

[1] 保存单个数组到文件

[2] 保存多个数组到文件

numpy.savze() 函数用于将多个数组写入文件,默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为 .npz 的文件中。

[3] 从文件加载数组

应用示例:

[4] 使用文本文件存取数组

numpy 也支持以文本文件存取数据。savetxt() 函数是以简单的文本文件格式存储数据,对应的使用 loadtxt() 函数来获取数据。

应用示例:

5. 常用函数

(1) 舍入函数

[1] 四舍五入

应用示例:

[2] 去尾和进一

应用示例:

(2) 数学函数

函数 说明

numpy.deg2rad() / numpy.radians()度转弧度

numpy.rad2deg() / numpy.degrees()弧度转度

numpy.sin()正弦函数

numpy.arcsin()反正弦函数

numpy.cos()余弦函数

numpy.arccos()反余弦函数

numpy.tan()正切函数

numpy.arctan()反正切函数

numpy.hypot()计算直角三角形斜边

numpy.square()平方

numpy.sqrt()开平方

numpy.power乘方

numpy.exp()指数

numpy.log()对数

numpy.log2()对数

numpy.log10()对数

(3) 统计函数

函数说明

numpy.sum(a[, axis, dtype, out, keepdims])按指定的轴求元素之和

numpy.nansum(a[, axis, dtype, out, keepdims])按指定的轴求元素之和,numpy.nan视为0

numpy.cumsum(a[, axis, dtype, out])按指定的轴求元素累进和

numpy.prod(a[, axis, dtype, out, keepdims])按指定的轴求元素之积

numpy.diff(a[, n, axis])返回相邻元素的差

numpy.ptp()返回数组中元素最大值与最小值的差

numpy.var()返回数组方差

numpy.std()返回数组标准差

numpy.median()返回数组元素的中位数

numpy.mean(a, axis=None, dtype=None, out=None, keepdims=)返回所有元素的算数平均值

numpy.average()根据权重数据,返回数据数组所有元素的夹权平均值

6. 牛刀小试

**例题 ** vertices 是若干三维空间随机点的集合,p 是三维空间的一点,找出 vertices 中距离 p 点最近的一个点,并计算它们的距离。

用 python 数组实现:

用 numpy 数组实现:

用随机方式生成1000个点,比较两种的方法的效率。


如果不懂 numpy,请别说自己是 python 程序员

以上就是小编为大家分享的所有内容,有想了解更多资讯或相关知识,可以关注公众号;程序员大咖(CodePush)

技术文章原创,最新视频分享等等,一大批干货正在路上,想看的朋友记得点关注哦!

发布于 2019-07-05 10:28

文章被以下专栏收录