生成数组的函数¶

arange¶

arange 类似于Python中的 range 函数,只不过返回的不是列表,而是数组:

  1. arange(start, stop=None, step=1, dtype=None)

产生一个在区间 [start, stop) 之间,以 step 为间隔的数组,如果只输入一个参数,则默认从 0 开始,并以这个值为结束:

In [1]:

  1. import numpy as np
  2. np.arange(4)

Out[1]:

  1. array([0, 1, 2, 3])

range 不同, arange 允许非整数值输入,产生一个非整型的数组:

In [2]:

  1. np.arange(0, 2 * np.pi, np.pi / 4)

Out[2]:

  1. array([ 0. , 0.78539816, 1.57079633, 2.35619449, 3.14159265,
  2. 3.92699082, 4.71238898, 5.49778714])

数组的类型默认由参数 start, stop, step 来确定,也可以指定:

In [3]:

  1. np.arange(0, 2 * np.pi, np.pi / 4, dtype=np.float32)

Out[3]:

  1. array([ 0. , 0.78539819, 1.57079637, 2.3561945 , 3.14159274,
  2. 3.92699099, 4.71238899, 5.49778748], dtype=float32)

由于存在精度问题,使用浮点数可能出现问题:

In [4]:

  1. np.arange(1.5, 2.1, 0.3)

Out[4]:

  1. array([ 1.5, 1.8, 2.1])

stop 的值 2.1 出现在了数组中,所以使用浮点数的时候需要注意。

linspace¶

  1. linspace(start, stop, N)

产生 N 个等距分布在 [start, stop]间的元素组成的数组,包括 start, stop

In [5]:

  1. np.linspace(0, 1, 5)

Out[5]:

  1. array([ 0. , 0.25, 0.5 , 0.75, 1. ])

logspace¶

  1. logspace(start, stop, N)

产生 N 个对数等距分布的数组,默认以10为底:

In [6]:

  1. np.logspace(0, 1, 5)

Out[6]:

  1. array([ 1. , 1.77827941, 3.16227766, 5.62341325, 10. ])

产生的值为$\left[10^0, 10^{0.25},10^{0.5},10^{0.75},10^1\right]$。

meshgrid¶

有时候需要在二维平面中生成一个网格,这时候可以使用 meshgrid 来完成这样的工作:

In [7]:

  1. x_ticks = np.linspace(-1, 1, 5)
  2. y_ticks = np.linspace(-1, 1, 5)
  3.  
  4. x, y = np.meshgrid(x_ticks, y_ticks)

这里产生的 x, y如下:

In [8]:

  1. x

Out[8]:

  1. array([[-1. , -0.5, 0. , 0.5, 1. ],
  2. [-1. , -0.5, 0. , 0.5, 1. ],
  3. [-1. , -0.5, 0. , 0.5, 1. ],
  4. [-1. , -0.5, 0. , 0.5, 1. ],
  5. [-1. , -0.5, 0. , 0.5, 1. ]])

In [9]:

  1. y

Out[9]:

  1. array([[-1. , -1. , -1. , -1. , -1. ],
  2. [-0.5, -0.5, -0.5, -0.5, -0.5],
  3. [ 0. , 0. , 0. , 0. , 0. ],
  4. [ 0.5, 0.5, 0.5, 0.5, 0.5],
  5. [ 1. , 1. , 1. , 1. , 1. ]])

x 对应网格的第一维,y 对应网格的第二维。

图例:

In [10]:

  1. %matplotlib inline
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. from matplotlib import cm
  5.  
  6. def f(x, y):
  7. # sinc 函数
  8. r = np.sqrt(x ** 2 + y ** 2)
  9. result = np.sin(r) / r
  10. result[r == 0] = 1.0
  11. return result
  12.  
  13. x_ticks = np.linspace(-10, 10, 51)
  14. y_ticks = np.linspace(-10, 10, 51)
  15.  
  16. x, y = np.meshgrid(x_ticks, y_ticks)
  17.  
  18. z = f(x, y)
  19.  
  20. fig = plt.figure()
  21. ax = fig.add_subplot(111, projection='3d')
  22. ax.plot_surface(x, y, z,
  23. rstride=1, cstride=1,
  24. cmap=cm.YlGnBu_r)
  25. ax.set_xlabel('x')
  26. ax.set_ylabel('y')
  27. ax.set_zlabel('z')
  1. c:\Miniconda\lib\site-packages\IPython\kernel\__main__.py:9: RuntimeWarning: invalid value encountered in divide

Out[10]:

  1. <matplotlib.text.Text at 0x9ac1630>

03.11 生成数组的函数 - 图1

事实上,x, y 中有很多冗余的元素,这里提供了一个 sparse 的选项:

In [11]:

  1. x_ticks = np.linspace(-1, 1, 5)
  2. y_ticks = np.linspace(-1, 1, 5)
  3.  
  4. x, y = np.meshgrid(x_ticks, y_ticks, sparse=True)

In [12]:

  1. x

Out[12]:

  1. array([[-1. , -0.5, 0. , 0.5, 1. ]])

In [13]:

  1. y

Out[13]:

  1. array([[-1. ],
  2. [-0.5],
  3. [ 0. ],
  4. [ 0.5],
  5. [ 1. ]])

在这个选项下,x, y 变成了单一的行向量和列向量。

但这并不影响结果:

In [14]:

  1. x_ticks = np.linspace(-10, 10, 51)
  2. y_ticks = np.linspace(-10, 10, 51)
  3.  
  4. x, y = np.meshgrid(x_ticks, y_ticks, sparse=True)
  5.  
  6. z = f(x, y)
  7.  
  8. fig = plt.figure()
  9. ax = fig.add_subplot(111, projection='3d')
  10. ax.plot_surface(x, y, z,
  11. rstride=1, cstride=1,
  12. cmap=cm.YlGnBu_r)
  13. ax.set_xlabel('x')
  14. ax.set_ylabel('y')
  15. ax.set_zlabel('z')
  1. c:\Miniconda\lib\site-packages\IPython\kernel\__main__.py:9: RuntimeWarning: invalid value encountered in divide

Out[14]:

  1. <matplotlib.text.Text at 0xba147f0>

03.11 生成数组的函数 - 图2

meshgrid 可以设置轴排列的先后顺序:

  • 默认为 indexing='xy' 即笛卡尔坐标,对于2维数组,返回行向量 x 和列向量 y
  • 或者使用 indexing='ij' 即矩阵坐标,对于2维数组,返回列向量 x 和行向量 y

ogrid , mgrid¶

Matlab中有 meshgrid 的用法:

  1. meshgrid(-1:.5:1, -1:.5:1)

Numpymeshgrid 并不支持这样的用法,但我们可以使用 ogrid / mgrid 来实现类似这样的用法。

ogridmgrid 的区别在于:

  • ogrid 相当于 meshgrid(indexing='ij', sparse=True)
  • mgrid 相当于 meshgrid(indexing='ij', sparse=False)

In [15]:

  1. x, y = np.ogrid[-1:1:.5, -1:1:.5]

In [16]:

  1. x

Out[16]:

  1. array([[-1. ],
  2. [-0.5],
  3. [ 0. ],
  4. [ 0.5]])

In [17]:

  1. y

Out[17]:

  1. array([[-1. , -0.5, 0. , 0.5]])

注意:

  • 这里使用的是中括号
  • Matlab 使用的是 start:step:end 的表示,Numpy 使用的是 start:end:step 的表示
  • 这里的结果不包括 end 的值
    为了包含 end 的值,我们可以使用这样的技巧:

In [18]:

  1. x, y = np.ogrid[-1:1:5j, -1:1:5j]

In [19]:

  1. x, y

Out[19]:

  1. (array([[-1. ],
  2. [-0.5],
  3. [ 0. ],
  4. [ 0.5],
  5. [ 1. ]]), array([[-1. , -0.5, 0. , 0.5, 1. ]]))

我们在 step 的位置传入一个复数 5j ,表示我们需要一个 5 个值的数组,此时返回值就会包含 end 的值。

重复之前的画图:

In [20]:

  1. # exchange here
  2. y, x = np.ogrid[-10:10:51j, -10:10:51j]
  3.  
  4. z = f(x, y)
  5.  
  6. fig = plt.figure()
  7. ax = fig.add_subplot(111, projection='3d')
  8. ax.plot_surface(x, y, z,
  9. rstride=1, cstride=1,
  10. cmap=cm.YlGnBu_r)
  11. ax.set_xlabel('x')
  12. ax.set_ylabel('y')
  13. ax.set_zlabel('z')
  1. c:\Miniconda\lib\site-packages\IPython\kernel\__main__.py:9: RuntimeWarning: invalid value encountered in divide

Out[20]:

  1. <matplotlib.text.Text at 0x9e34278>

03.11 生成数组的函数 - 图5

这里,我们交换了 x, y 输出值的顺序。

r , c

我们可以使用 r / c 来产生行向量或者列向量。

使用切片产生:

In [21]:

  1. np.r_[0:1:.1]

Out[21]:

  1. array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])

复数步长制定数组长度:

In [22]:

  1. np.r_[0:1:5j]

Out[22]:

  1. array([ 0. , 0.25, 0.5 , 0.75, 1. ])

连接多个序列,产生数组:

In [23]:

  1. np.r_[(3,22,11), 4.0, [15, 6]]

Out[23]:

  1. array([ 3., 22., 11., 4., 15., 6.])

列向量:

In [24]:

  1. np.c_[1:3:5j]

Out[24]:

  1. array([[ 1. ],
  2. [ 1.5],
  3. [ 2. ],
  4. [ 2.5],
  5. [ 3. ]])

ones , zeros¶

  1. ones(shape, dtype=float64)
  2. zeros(shape, dtype=float64)

产生一个制定形状的全 0 或全 1 的数组,还可以制定数组类型:

In [25]:

  1. np.zeros(3)

Out[25]:

  1. array([ 0., 0., 0.])

In [26]:

  1. np.ones([2,3], dtype=np.float32)

Out[26]:

  1. array([[ 1., 1., 1.],
  2. [ 1., 1., 1.]], dtype=float32)

产生一个全是 5 的数组:

In [27]:

  1. np.ones([2,3]) * 5

Out[27]:

  1. array([[ 5., 5., 5.],
  2. [ 5., 5., 5.]])

empty¶

  1. empty(shape, dtype=float64, order='C')

也可以使用 empty 方法产生一个制定大小的数组(数组所指向的内存未被初始化,所以值随机),再用 fill 方法填充:

In [28]:

  1. a = np.empty(2)
  2. a

Out[28]:

  1. array([-0.03412165, 0.05516321])

In [29]:

  1. a.fill(5)
  2. a

Out[29]:

  1. array([ 5., 5.])

另一种替代方法使用索引,不过速度会稍微慢一些:

In [30]:

  1. a[:] = 5
  2. a

Out[30]:

  1. array([ 5., 5.])

empty_like, ones_like, zeros_like¶

  1. empty_like(a)
  2. ones_like(a)
  3. zeros_like(a)

产生一个跟 a 大小一样,类型一样的对应数组。

In [31]:

  1. a = np.arange(0, 10, 2.5)
  2. a

Out[31]:

  1. array([ 0. , 2.5, 5. , 7.5])

In [32]:

  1. np.empty_like(a)

Out[32]:

  1. array([ 0., 0., 0., 0.])

In [33]:

  1. np.zeros_like(a)

Out[33]:

  1. array([ 0., 0., 0., 0.])

In [34]:

  1. np.ones_like(a)

Out[34]:

  1. array([ 1., 1., 1., 1.])

identity¶

  1. indentity(n, dtype=float64)

产生一个 nn 的单位矩阵:

In [35]:

  1. np.identity(3)

Out[35]:

  1. array([[ 1., 0., 0.],
  2. [ 0., 1., 0.],
  3. [ 0., 0., 1.]])

原文: https://nbviewer.jupyter.org/github/lijin-THU/notes-python/blob/master/03-numpy/03.11-array-creation-functions.ipynb