Python中的NumPy。 第三部分

译者序


你好! 继续我们有关翻译有关numpy的法力的系列文章。 阅读愉快。


比较运算符和价值测试


布尔比较可用于元素比较具有相同长度的数组。 返回值是布尔值True / False的数组:

>>> a = np.array([1, 3, 0], float) >>> b = np.array([0, 3, 2], float) >>> a > b array([ True, False, False], dtype=bool) >>> a == b array([False, True, False], dtype=bool) >>> a <= b array([False, True, True], dtype=bool) 

比较结果可以存储在数组中:

 >>> c = a > b >>> c array([ True, False, False], dtype=bool) 

可以将数组与单个值进行比较:

 >>> a = np.array([1, 3, 0], float) >>> a > 2 array([False, True, False], dtype=bool) 

any和all运算符可分别用于确定至少一个或所有元素为true:

 >>> c = np.array([ True, False, False], bool) >>> any(c) True >>> all(c) False 

可以使用特殊功能logical_and,logical_or和logical_not在单个元素的基础上将组合的布尔表达式应用于数组:

 >>> a = np.array([1, 3, 0], float) >>> np.logical_and(a > 0, a < 3) array([ True, False, False], dtype=bool) >>> b = np.array([True, False, True], bool) >>> np.logical_not(b) array([False, True, False], dtype=bool) >>> c = np.array([False, True, False], bool) >>> np.logical_or(b, c) array([ True, True, False], dtype=bool) 

where函数使用布尔过滤器从两个相同长度的其他数组中创建一个新数组,以在两个元素之间进行选择。 基本语法:where(boolarray,
truearray,falsearray):

 >>> a = np.array([1, 3, 0], float) >>> np.where(a != 0, 1 / a, a) array([ 1. , 0.33333333, 0. ]) 

使用where函数,还可以实现质量比较:

 >>> np.where(a > 0, 3, 2) array([3, 3, 2]) 

一些函数可以测试数组中的值。 非零函数返回非零值索引的元组。 元组中的元素数等于数组中的轴数:

 >>> a = np.array([[0, 1], [3, 0]], float) >>> a.nonzero() (array([0, 1]), array([1, 0])) 

您还可以检查有限性和NaN的值(不是数字):

 >>> a = np.array([1, np.NaN, np.Inf], float) >>> a array([ 1., NaN, Inf]) >>> np.isnan(a) array([False, True, False], dtype=bool) >>> np.isfinite(a) array([ True, False, False], dtype=bool) 

尽管我们在这里使用了numpy常数来添加NaN和无穷大,但是它们可以是应用标准数学运算的结果。

选择和操作数组元素


我们已经看到,与列表一样,可以通过按索引使用访问操作来获取数组元素。 但是,与列表不同,数组还允许您使用其他数组选择项目。 这意味着我们可以使用一个数组来过滤其他数组元素的特定子集。

布尔数组可以用作过滤数组:

 >>> a = np.array([[6, 4], [5, 9]], float) >>> a >= 6 array([[ True, False], [False, True]], dtype=bool) >>> a[a >= 6] array([ 6., 9.]) 

值得注意的是,当我们通过数组a的索引传递布尔数组a> = 6作为访问操作的索引时,返回的数组将仅存储True值。 我们还可以编写一个数组以过滤为变量:

 >>> a = np.array([[6, 4], [5, 9]], float) >>> sel = (a >= 6) >>> a[sel] array([ 6., 9.]) 

使用布尔表达式可以实现更复杂的过滤:

 >>> a[np.logical_and(a > 5, a < 9)] >>> array([ 6.]) 

除了布尔选择之外,您还可以使用整数数组。 在这种情况下,整数数组存储要从数组中获取的元素的索引。 考虑下面的一维示例:

 >>> a = np.array([2, 4, 6, 8], float) >>> b = np.array([0, 0, 1, 3, 2, 1], int) >>> a[b] array([ 2., 2., 4., 8., 6., 4.]) 

换句话说,当我们使用b从a中获取元素时,我们将按此顺序获取a的第0、0、1、3、2和1元素。 列表也可以用作过滤数组:

 >>> a = np.array([2, 4, 6, 8], float) >>> a[[0, 0, 1, 3, 2, 1]] array([ 2., 2., 4., 8., 6., 4.]) 

对于多维数组,我们需要将每个轴的几个一维整数数组传输到访问运算符索引( 注意转换器:在我们的情况下,索引是array )。 然后,每个数组都按照以下顺序进行操作:第一个元素对应于行的索引,它是数组b的第一个元素,第二个元素对应于列的索引,它是数组c的第一个元素,依此类推。 ( 转换器的注释:第一个数组[2,2]和第二个[1,4],我们在输出中有带有索引[2,1]和[2,4]的元素 )示例:

 >>> a = np.array([[1, 4], [9, 16]], float) >>> b = np.array([0, 0, 1, 1, 0], int) >>> c = np.array([0, 1, 1, 1, 1], int) >>> a[b,c] array([ 1., 4., 16., 16., 4.]) 

一个特殊的take函数可用于整数数组的获取。 这与对索引使用take运算符的作用相同:

 >>> a = np.array([2, 4, 6, 8], float) >>> b = np.array([0, 0, 1, 3, 2, 1], int) >>> a.take(b) array([ 2., 2., 4., 8., 6., 4.]) 

Take函数还提供axis参数,以沿轴对多维数组的一部分进行剖分。 ( 注意翻译器:行或列(用于二维数组) )。

 >>> a = np.array([[0, 1], [2, 3]], float) >>> b = np.array([0, 0, 1], int) >>> a.take(b, axis=0) array([[ 0., 1.], [ 0., 1.], [ 2., 3.]]) >>> a.take(b, axis=1) array([[ 0., 0., 1.], [ 2., 2., 3.]]) 

与take函数相反,有一个put函数,它将从原始数组中获取值并将它们写入另一个put数组中的特定索引。

 >>> a = np.array([0, 1, 2, 3, 4, 5], float) >>> b = np.array([9, 8, 7], float) >>> a.put([0, 3], b) >>> a array([ 9., 1., 2., 8., 4., 5.]) 

注意,由于仅指示2个索引[0,3],因此未使用原始数组b中的值7。 如果长度不匹配,将在必要时重复原始数组:

 >>> a = np.array([0, 1, 2, 3, 4, 5], float) >>> a.put([0, 3], 5) >>> a array([ 5., 1., 2., 5., 4., 5.]) 

向量和矩阵数学


NumPy提供了许多用于处理向量和矩阵的函数。 点函数返回向量的标量积:

 >>> a = np.array([1, 2, 3], float) >>> b = np.array([0, 1, 1], float) >>> np.dot(a, b) 5.0 

点函数还可以将矩阵相乘:

 >>> a = np.array([[0, 1], [2, 3]], float) >>> b = np.array([2, 3], float) >>> c = np.array([[1, 1], [4, 0]], float) >>> a array([[ 0., 1.], [ 2., 3.]]) >>> np.dot(b, a) array([ 6., 11.]) >>> np.dot(a, b) array([ 3., 13.]) >>> np.dot(a, c) array([[ 4., 0.], [ 14., 2.]]) >>> np.dot(c, a) array([[ 2., 4.], [ 0., 4.]]) 

您还可以获得矩阵和向量的标量,张量和外积。 请注意,对于向量,内部乘积和标量乘积是重合的。

 >>> a = np.array([1, 4, 0], float) >>> b = np.array([2, 2, 1], float) >>> np.outer(a, b) array([[ 2., 2., 1.], [ 8., 8., 4.], [ 0., 0., 0.]]) >>> np.inner(a, b) 10.0 >>> np.cross(a, b) array([ 4., -1., -6.]) 

NumPy还提供了一组用于处理线性代数的内置函数和方法。 所有这些都可以在linalg子模块中找到。 这些模块也可以在退化和非退化矩阵上运行。 矩阵的行列式以这种方式搜索:

 >>> a = np.array([[4, 2, 0], [9, 3, 7], [1, 2, 1]], float) >>> a array([[ 4., 2., 0.], [ 9., 3., 7.], [ 1., 2., 1.]]) >>> np.linalg.det(a) -48. 

您还可以找到矩阵的特征向量和特征值:

 >>> vals, vecs = np.linalg.eig(a) >>> vals array([ 9. , 2.44948974, -2.44948974]) >>> vecs array([[-0.3538921 , -0.56786837, 0.27843404], [-0.88473024, 0.44024287, -0.89787873], [-0.30333608, 0.69549388, 0.34101066]]) 

非简并矩阵可以找到如下:

 >>> b = np.linalg.inv(a) >>> b array([[ 0.14814815, 0.07407407, -0.25925926], [ 0.2037037 , -0.14814815, 0.51851852], [-0.27777778, 0.11111111, 0.11111111]]) >>> np.dot(a, b) array([[ 1.00000000e+00, 5.55111512e-17, 2.22044605e-16], [ 0.00000000e+00, 1.00000000e+00, 5.55111512e-16], [ 1.11022302e-16, 0.00000000e+00, 1.00000000e+00]]) 

可以如下实现单个分解(非方矩阵的对角化的模拟):

 >>> a = np.array([[1, 3,4], [5, 2, 3]], float) >>> U, s, Vh = np.linalg.svd(a) >>> U array([[-0.6113829 , -0.79133492], [-0.79133492, 0.6113829 ]]) >>> s array([ 7.46791327, 2.86884495]) >>> Vh array([[-0.61169129, -0.45753324, -0.64536587], [ 0.78971838, -0.40129005, -0.46401635], [-0.046676 , -0.79349205, 0.60678804]]) 

我们完成了第三部分。 祝你好运,很快再见!

Source: https://habr.com/ru/post/zh-CN413381/


All Articles