文章目录
- 生成序列
- 创建网格
- 创建特殊数组
- 随机数组
Python科学计算系列:数组
正所谓巧妇难为无米之炊,没有数据,也就没法对数据进行分析,从而数值计算也就成了无根之木了。所以,在学习具体的数值计算方法之前,先介绍几种特殊数据的生成方法。
生成序列
在科学计算时,会经常遇到生成序列的需求,比如前面演示差分、累加时就通过arange生成了一组自然数列。并且为了让相邻元素间隔 0.1 0.1 0.1,还在后面除以10。然而,arange这个函数,其实是有能力生成间隔为0.1的序列的。
此外,【linspace】也可以生成等差数列,二者区别如下
linspace(a,b,N)
在 [ a , b ] [a,b] [a,b]中间生成 N N N个值, N N N默认为50arange(a,b,delta)
在 [ a , b ) [a,b) [a,b)之间,以 δ \delta δ为间隔生成值, δ \delta δ默认为1
所以,若想实现 [ 0 , 10 ) [0,10) [0,10)之间间隔为0.1的等差数列,这两个函数都可以做到,但需注意,linspace函数对两个端点默认是封闭的。
x = np.arange(0,10,0.1)
x = np.linspace(0,9.9,100)
x = np.linspace(0,10,100,endpoint=False)
除了等差数列之外,【logspace】和【geomspace】函数,可生成等比数列,二者区别如下
logspace(a,b,N,base=c)
在 [ c a , c b ] [c^a, c^b] [ca,cb] 之间等比生成N个值geomspace(a,b,N,base=c)
在 [ a , b ] [a,b] [a,b]之间,等比生成N个值
base
参数可表示对数的底。取
a
=
1
,
b
=
2
,
N
=
20
a=1, b=2, N=20
a=1,b=2,N=20,二者差别如下
绘图代码为
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(1,2,20)
y = {"logspace" : np.logspace(1,2,20),
"geomspace" : np.geomspace(1,2,20)}
fig = plt.figure()
for i,key in zip([1,2],y.keys()):
ax = fig.add_subplot(1,2,i)
ax.plot(x,y[key],marker="*")
ax.set_title(key)
plt.show()
创建网格
在三维图的绘制过程中,一般需要 x , y , z x,y,z x,y,z之间的对应关系,但对于图像而言,其 x , y x,y x,y轴坐标是体现在像素栅格中的,从而图像矩阵中的像素强度,其实表示的是 z z z轴的坐标,这种情况下如果想绘制三维散点图,就需要生成图像像素对应的坐标网格。
这种网格形式大致如下,其中 x v x_v xv的 y y y轴不变,而 x x x轴等差增长,与坐标轴等比例映射, y v y_v yv同理。
x v = [ 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 ] y v = [ 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 ] x_v=\begin{bmatrix} 1&2&3&4\\1&2&3&4\\1&2&3&4\\1&2&3&4\\ \end{bmatrix}\quad y_v=\begin{bmatrix} 0&0&0&0\\1&1&1&1\\2&2&2&2\\3&3&3&3\\ \end{bmatrix} xv= 1111222233334444 yv= 0123012301230123
【meshgrid】是Python中最常用的坐标网格生成函数,可将输入的 x , y x,y x,y变量,向 y y y轴和 x x x轴方向进行扩张。如想生成 x v , y v x_v, y_v xv,yv,方法如下
x = [1,2,3,4]
y = [0,1,2,3]
xv, yv = np.meshgrid(x, y)
【mgrid】比meshgrid更加简单,可以直接通过魔法函数用索引语法来生成坐标网格,
yv, xv = np.mgrid[:4, 1:5]
np.mgrid[1:5] # [1, 2, 3, 4]
np.mgrid[1:10:5] # [1, 6]
np.mgrid[1.1:10] # [1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1, 9.1]
如果翻阅源码,会发现mgrid是MGridClass
的一个实例,MGridClass
则是nd_grid
的一个子类,在nd_grid
中,实现了__getitem__
这个魔法函数,从而支持方括号语法来生成数据。。
【ogrid】的用法与mgrid相同,同样是nd_grid的子类,但生成的数组不同,直接看案例
x,y = ogrid[0:5,0:5]
其中, x = [ 0 , 1 , 2 , 3 , 4 ] T x=[0,1,2,3,4]^T x=[0,1,2,3,4]T, y = [ 0 , 1 , 2 , 3 , 4 ] y=[0,1,2,3,4] y=[0,1,2,3,4]。
如果想干脆一点,只是生成从0开始的等间隔的坐标网格,那么这里最推荐的是【indices】,这个函数只需输入维度,就可以完成网格的创建。
创建特殊数组
numpy提供了一系列函数用以生成特殊数组,列表如下。所有这些函数中,都有一个可选参数dtype
,表示创建的数组的数据类型。
类别 | 函数 |
---|---|
指定维度 | empty , ones , zeros , full , eye , identity |
模仿维度 | empty_like , ones_like , zeros_like , full_like |
特殊矩阵 | diag , diagflat , tri , tril , triu , vander |
【empty】生成指定维度的空数组。
【ones】, 【zeros】和【full】生成所有元素都相同的数组,顾名思义,前两者分别是全1和全0的数组,而full可通过参数fill_value来指定填充的数值。
以【_like】为后缀的函数,表示生成一个和输入数组维度相同的数组,例如,np.ones_like(x)
等价于np.ones(x.shape)
。
np.ones(3) #生成全1的3x1数组
np.zeros([2,3]) #生成全0的2x3数组
x = np.full([2,4], 5) #生成元素均为5的2x4数组
y = np.full_like(x, 6)
【eye】和【identity】都是生成对角为1,其他元素为0的矩阵,区别在于,前者只能生成单位矩阵,即方阵;后者则无此要求。【diagflat】和【diag】用于生成对角矩阵,这几种矩阵的区别如下。
【diag】在diagflat基础上,还可以提取对角元素,例如
np.diag(np.ones([3,3])) #提取对角元素 [1., 1., 1.]
【tri(M,N,k)】用于生成M行N列的三角阵,其元素为0或者1,k
用于调节$0和
1
1
1的分界线相对于对角线的位置,下图中,红色表示
1
1
1,蓝色表示
0
0
0.
【tril, triu】可用于提取出矩阵的左下和右上的三角阵,其输入参数除了待提取矩阵之外,另一个参数与tri
中的k
相同,把x设为
x = np.arange(20).reshape(4, 5)
则tril
和triu
作用在x上的效果分别如下,二者分别把右上角和左下角的值变成了0。
【vander】可通过给定的 α i \alpha_i αi生成范德蒙德矩阵。对于 m × ( n + 1 ) m\times(n+1) m×(n+1)的范德蒙德矩阵 V V V,其矩阵元可表示为对可表示为 V i j = α i j V_{ij}=\alpha_i^j Vij=αij,示例如下
x = np.array([1, 2, 3, 5])
V = np.vander(x, increasing=True)
其结果为
V = [ 1 1 1 1 1 2 4 8 1 3 6 9 1 5 25 125 ] V=\begin{bmatrix} 1&1&1&1\\1&2&4&8\\1&3&6&9\\1&5&25&125 \end{bmatrix} V= 1111123514625189125
随机数组
numpy中提供了【random】模块,可用于随机数组的生成,其中又以【rand】函数最为常用,其使用频次仅次于arange。
一个更加规范的随机数创建过程,往往需要指定随机数种子,以便于复现。
np.random.seed(42)
np.random.rand(2,2)
其返回值如下。
[ 0.37454012 0.95071431 0.73199394 0.59865848 ] \begin{bmatrix} 0.37454012&0.95071431\\ 0.73199394&0.59865848 \end{bmatrix} [0.374540120.731993940.950714310.59865848]
众所周知,我们所调用的随机数,其实是伪随机数,本质是查阅随机数表。而【seed】函数,可以理解为查阅这个表的起始位置,所以这个数指定了,那么后期所有的“随机数”的值也就确定了。
除了numpy之外,Python标准库【random】也提供了随机数表,即可用于随机数的生成,但其输出仅为浮点数,示例如下
import random
random.seed(42)
random.random()
# 0.6394267984578837