
Numpy图解(一)--向量
目录Numpy数组与Python列表Numpy向量向量初始化向量索引向量运算Numpy数组与Python列表它们都可以用作容器,具有获取(getting)和设置(setting)元素以及插入和移除元素的功能。两者有很多相似之处,以下是二者在运算时的一个示例:和Python列表相比,Numpy数组具有以下特点:更紧凑,尤其是在一维以上的维度;向量化操作时比Python列表快,但在末尾添加元素比Pyt
目录
Numpy数组与Python列表
它们都可以用作容器,具有获取(getting)和设置(setting)元素以及插入和移除元素的功能。
两者有很多相似之处,以下是二者在运算时的一个示例:
和Python列表相比,Numpy数组具有以下特点:
更紧凑,尤其是在一维以上的维度;向量化操作时比Python列表快,但在末尾添加元素比Python列表慢。
△在末尾添加元素时,Python列表复杂度为O(1),NumPy复杂度为O(N)
Numpy向量
向量初始化
创建NumPy数组的一种方法是从Python列表直接转换,数组元素的类型与列表元素类型相同。
NumPy数组无法像Python列表那样加长,因为在数组末尾没有保留空间。
因此,常见的做法是定义一个Python列表,对它进行操作,然后再转换为NumPy数组,或者用np.zeros和np.empty初始化数组,预分配必要的空间:
有时我们需要创建一个空数组,大小和元素类型与现有数组相同:
实际上,所有用常量填充创建的数组的函数都有一个_like对应项,来创建相同类型的常数数组:
在NumPy中,可以用arange或者linspace来初始化单调序列数组:
如果需要类似[0., 1., 2.]的浮点数组,可以更改arange输出的类型:arange(3).astype(float)。
但是有更好的方法:arange函数对数据类型敏感,如果将整数作为参数,生成整数数组;如果输入浮点数(例如arange(3.)),则生成浮点数组。
但是arange在处理浮点数方面并不是特别擅长:
这是因为0.1对于我们来说是一个有限的十进制数,但对计算机而言却不是。在二进制下,0.1是一个无穷小数,必须在某处截断。
这就是为什么将小数部分加到步骤arange通常是一个不太好的方法:我们可能会遇到一个bug,导致数组的元素个数不是我们想要的数,这会降低代码的可读性和可维护性。
这时候,linspace会派上用场。它不受舍入错误的影响,并始终生成要求的元素数。
出于测试目的,通常需要生成随机数组,NumPy提供随机整数、均匀分布、正态分布等几种随机数形式:
向量索引
一旦将数据存储在数组中,NumPy便会提供简单的方法将其取出:
上面展示了各式各样的索引,例如取出某个特定区间,从右往左索引、只取出奇数位等等。
但它们都是所谓的view,也就是不存储原始数据。并且如果原始数组在被索引后进行更改,则不会反映原始数组的改变。
这些索引方法允许分配修改原始数组的内容,因此需要特别注意:只有下面最后一种方法才是复制数组,如果用其他方法都可能破坏原始数据:
从NumPy数组中获取数据的另一种超级有用的方法是布尔索引,它允许使用各种逻辑运算符,来检索符合条件的元素:
注意:Python中的三元比较3<=a<=5在NumPy数组中不起作用。
如上所述,布尔索引也会改写数组。它有两个常见的函数,分别是np.where和np.clip:
向量运算
算术运算是NumPy速度最引入注目的地方之一。NumPy的向量运算符已达到C++级别,避免了Python的慢循环。
基本数学运算
NumPy允许像普通数字一样操作整个数组(加减乘除、整除、幂):
△ 和Python中一样,a//b表示div b(整除),x**n表示xⁿ
向量还可以与标量进行类似的运算,方法相同:
大多数的数学函数都有NumPy对应项用于处理向量:
向量的点积、叉积运算:
三角函数、反三角函数、求斜边运算:
数组可以四舍五入运算(整数):
△ floor取下界;ceil取上界;round为四舍六入五取偶
基本的统计运算(最大最小值、平均值、方差、标准差):
不过排序函数的功能比Python列表对应函数更少:
搜索向量中的元素
与Python列表相反,NumPy数组没有index方法。
-
查找元素的一种方法是np.where(a==x)[0][0],它既不优雅也不快速,因为要查找的项需要从开头遍历数组的所有元素。
-
更快的方式是通过Numba中的next((i[0] for i, v in np.ndenumerate(a) if v==x), -1)来加速。
-
一旦对数组进行排序,情况就会变得更好:v = np.searchsorted(a, x); return v if a[v]==x else -1的复杂度为O(log N),确实非常快,但是首先需要O(N log N)的排序时间。
函数np.allclose(a, b)用于比较具有给定公差的浮点数组:
-
np.allclose假设所有的比较数字的等级是1个单位。例如在上图中,它就认为1e-9和2e-9相同,如果要进行更细致的比较,需要通过atol指定比较等级1:np.allclose(1e-9, 2e-9, atol=1e-17) == False。
-
math.isclose进行比较没有假设前提,而是基于用户给出的一个合理abs_tol值:math.isclose(0.1+0.2–0.3, abs_tol=1e-8) == True。
除此之外np.allclose在绝对和相对公差公式中还存在一些小问题,例如,对某些数存在allclose(a, b) != allclose(b, a)。这些问题已在math.isclose函数中得到解决。
更多推荐
所有评论(0)