写点什么

NumPy 之:ndarray 中的函数

发布于: 2021 年 05 月 24 日

简介

在 NumPy 中,多维数组除了基本的算数运算之外,还内置了一些非常有用的函数,可以加快我们的科学计算的速度。

简单函数

我们先看下比较常见的运算函数,在使用之前,我们先构造一个数组:

arr = np.arange(10)
复制代码


array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
复制代码

计算数组中元素的开方:

np.sqrt(arr)
复制代码


array([0.    , 1.    , 1.4142, 1.7321, 2.    , 2.2361, 2.4495, 2.6458,       2.8284, 3.    ])
复制代码

自然常数 e 为底的指数函数:

np.exp(arr)
复制代码


array([   1.    ,    2.7183,    7.3891,   20.0855,   54.5982,  148.4132,        403.4288, 1096.6332, 2980.958 , 8103.0839])
复制代码

取两个数组的最大值,组成新的数组:

x = np.random.randn(8)y = np.random.randn(8)x,y
复制代码


(array([-2.3594, -0.1995, -1.542 , -0.9707, -1.307 ,  0.2863,  0.378 ,        -0.7539]), array([ 0.3313,  1.3497,  0.0699,  0.2467, -0.0119,  1.0048,  1.3272,        -0.9193]))
复制代码


np.maximum(x, y)
复制代码


array([ 0.3313,  1.3497,  0.0699,  0.2467, -0.0119,  1.0048,  1.3272,       -0.7539])
复制代码

返 回浮点数数组的小数和整数部分:

arr = np.random.randn(7) * 5
复制代码


array([-7.7455,  0.1109,  3.7918, -3.3026,  4.3129, -0.0502,  0.25  ])
复制代码


remainder, whole_part = np.modf(arr)
复制代码


(array([-0.7455,  0.1109,  0.7918, -0.3026,  0.3129, -0.0502,  0.25  ]), array([-7.,  0.,  3., -3.,  4., -0.,  0.]))
复制代码

矢量化数组运算

如果要进行数组之间的运算,常用的方法就是进行循环遍历,但是这样的效率会比较低。所以 Numpy 提供了数组之间的数据处理的方法。

先来讲解一下 np.meshgrid 这个函数,这个函数是用来快速生成网格点坐标矩阵的。

先看一段坐标点的代码:

import numpy as npimport matplotlib.pyplot as plt
x = np.array([[0, 1, 2], [0, 1, 2]])y = np.array([[0, 0, 0], [1, 1, 1]])

plt.plot(x, y, color='green', marker='.', linestyle='')plt.grid(True)plt.show()
复制代码

上面的 X 是一个二维数组,表示的是坐标点的 X 轴的位置。

Y 也是一个二维数组,表示的是坐标点的 Y 轴的位置。

看下画出来的图像:



上面画出的就是使用 X,Y 矩阵组合出来的 6 个坐标点。

上面的 X,Y 的二维数组是我们手动输入的,如果坐标上面有大量点的话,手动输入肯定是不可取的。

于是有了 np.meshgrid 这个函数。这个函数可以接受两个一维的数组,然后生成二维的 X,Y 坐标矩阵。

上面的例子可以改写为:

x = np.array([0,1,2])y = np.array([0,1])
xs, ys = np.meshgrid(x, y)xs,ys(array([[0, 1, 2], [0, 1, 2]]), array([[0, 0, 0], [1, 1, 1]]))
复制代码

可以看到生成的 xs 和 ys 和手动输入是一样的。

有了网格坐标之后,我们就可以基于网格值来计算一些数据,比如:sqrt(x^2+y^2)sqrt(x2+y2) ,我们不用变量矩阵中所有的数据,只需要直接使用数组进行运算即可:

np.sqrt(xs ** 2 + ys ** 2)
复制代码

结果:

array([[0.        , 1.        , 2.        ],       [1.        , 1.41421356, 2.23606798]])
复制代码

因为 xs 和 ys 本身就是 2 * 3 的矩阵,所以结果也是 2 * 3 的矩阵。

条件逻辑表达式

我们可以在构建数组的时候使用条件逻辑表达式:

xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])cond = np.array([True, False, True, True, False])
复制代码


result = [(x if c else y)          for x, y, c in zip(xarr, yarr, cond)]result
复制代码


[1.1, 2.2, 1.3, 1.4, 2.5]
复制代码

更简单一点,我们可以使用 where 语句:

result = np.where(cond, xarr, yarr)result
复制代码


array([1.1, 2.2, 1.3, 1.4, 2.5])
复制代码

我们还可以根据 where 的条件来修改数组的值:

arr = np.random.randn(4, 4)arrarray([[ 0.7953,  0.1181, -0.7485,  0.585 ],       [ 0.1527, -1.5657, -0.5625, -0.0327],       [-0.929 , -0.4826, -0.0363,  1.0954],       [ 0.9809, -0.5895,  1.5817, -0.5287]])

复制代码

上面我们构建了一个 4 * 4 的数组。

我们可以在 where 中进行数据的比较,如果大于 0,将数据修改成 2 ,如果小于 0,则将数据修该成-2 :

np.where(arr > 0, 2, -2)array([[ 2,  2, -2,  2],       [ 2, -2, -2, -2],       [-2, -2, -2,  2],       [ 2, -2,  2, -2]])
复制代码

统计方法

numpy 提供了 mean,sum 等统计方法:

arr = np.random.randn(5, 4)arrarr.mean()np.mean(arr)arr.sum()
复制代码

还可以按维度来统计:

arr.mean(axis=1)arr.sum(axis=0)
复制代码

cumsum 进行累加计算:

arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])arr.cumsum()
复制代码


array([ 0,  1,  3,  6, 10, 15, 21, 28])
复制代码

cumprod 进行累乘计算:

arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])arrarr.cumsum(axis=0)
复制代码


array([[ 0,  1,  2],       [ 3,  5,  7],       [ 9, 12, 15]])
复制代码


arr.cumprod(axis=1)
复制代码


array([[  0,   0,   0],       [  3,  12,  60],       [  6,  42, 336]])
复制代码

布尔数组

any 用于测试数组中是否存在一个或多个 True,而 all 则检查数组中所有值是否都是 True:

bools = np.array([False, False, True, False])bools.any()True
复制代码


bools.all()False
复制代码

排序

使用 sort 可以对数组进行排序,除了普通排序还可以按照特定的轴来进行排序:

arr = np.random.randn(6)arr.sort()
复制代码


array([-2.5579, -1.2943, -0.2972, -0.1516,  0.0765,  0.1608])
复制代码


arr = np.random.randn(5, 3)arrarr.sort(1)arr
复制代码


array([[-0.8852, -0.4936, -0.1875],       [-0.3507, -0.1154,  0.0447],       [-1.1512, -0.8978,  0.8909],       [-2.6123, -0.8671,  1.1413],       [-0.437 ,  0.3475,  0.3836]])
复制代码

sort(1)指的是按照第二个轴来排序。

文件

可以方便的将数组写入到文件和从文件中读出:

arr = np.arange(10)np.save('some_array', arr)
复制代码

会将数组存放到 some_array.npy 文件中,我们可以这样读取:

np.load('some_array.npy')
复制代码

还可以以无压缩的方式存入多个数组:

np.savez('array_archive.npz', a=arr, b=arr)
复制代码

读取:

arch = np.load('array_archive.npz')arch['b']
复制代码

如果想要压缩,可以这样:

np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)
复制代码

线性代数

如果我们使用普通的算数符来进行矩阵的运算的话,只是简单的数组中对应的元素的算数运算。如果我们想做矩阵之间的乘法的时候,可以使用 dot。

一个 2 * 3 的矩阵 dot 一个 3*2 的矩阵,最终得到一个 2 * 2 的矩阵。

x = np.array([[1., 2., 3.], [4., 5., 6.]])y = np.array([[6., 23.], [-1, 7], [8, 9]])xyx.dot(y)
复制代码


array([[ 28.,  64.],       [ 67., 181.]])
复制代码

或者可以这样写:

np.dot(x, y)
复制代码


array([[ 28.,  64.],       [ 67., 181.]])
复制代码

还可以使用 @ 符号:

x @ y
复制代码


array([[ 28.,  64.],       [ 67., 181.]])
复制代码

我们看下都有哪些运算:

乘积运算:

分解运算:

本征值和本征向量:

基准值:

求解和反转:

随机数

很多时候我们都需要生成随机数,在 NumPy 中随机数的生成非常简单:

samples = np.random.normal(size=(4, 4))samples
复制代码


array([[-2.0016, -0.3718,  1.669 , -0.4386],       [-0.5397,  0.477 ,  3.2489, -1.0212],       [-0.5771,  0.1241,  0.3026,  0.5238],       [ 0.0009,  1.3438, -0.7135, -0.8312]])
复制代码

上面用 normal 来得到一个标准正态分布的 4×4 样本数组。

使用 np.random 要比使用 Python 自带的随机数生成器要快得多。

np.random 可以指定生成随机数的种子:

np.random.seed(1234)
复制代码

numpy.random 的数据生成函数使用了全局的随机种子。要避免 全局状态,你可以使用 numpy.random.RandomState,创建一个 与其它隔离的随机数生成器:

rng = np.random.RandomState(1234)rng.randn(10)
复制代码

本文已收录于 http://www.flydean.com/10-python-numpy-func/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2021 年 05 月 24 日阅读数: 24
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
NumPy之:ndarray中的函数