NumPy 1.26 中文官方指南(一)(4)

简介: NumPy 1.26 中文官方指南(一)

NumPy 1.26 中文官方指南(一)(3)https://developer.aliyun.com/article/1510634

较不基本

广播规则

广播使得通用函数可以对不完全相同形状的输入进行有意义的处理。

广播的第一个规则是,如果所有的输入数组的维度数不相同,则“1”将被重复添加到较小数组的形状之前,直到所有数组具有相同的维度数。

第二个广播规则确保在特定维度上大小为 1 的数组,表现得就像它们在该维度上的最大形状的数组一样。假设“广播”数组在该维度上的数组元素值是相同的。

应用广播规则后,所有数组的大小必须匹配。更多细节请参见广播。 ### 广播规则

广播使得通用函数可以对不完全相同形状的输入进行有意义的处理。

广播的第一个规则是,如果所有的输入数组的维度数不相同,则“1”将被重复添加到较小数组的形状之前,直到所有数组具有相同的维度数。

广播的第二规则确保在特定维度上大小为 1 的数组会像在该维度上具有最大形状的数组一样起作用。假定在广播数组中,数组元素的值沿该维度是相同的。

应用广播规则后,所有数组的大小必须匹配。更多细节可以在 广播 中找到。

高级索引和索引技巧

NumPy 提供的索引功能比常规 Python 序列更多。除了之前看到的通过整数和切片进行索引外,数组还可以通过整数数组和布尔数组进行索引。

使用索引数组进行索引

>>> a = np.arange(12)**2  # the first 12 square numbers
>>> i = np.array([1, 1, 3, 8, 5])  # an array of indices
>>> a[i]  # the elements of `a` at the positions `i`
array([ 1,  1,  9, 64, 25])
>>>
>>> j = np.array([[3, 4], [9, 7]])  # a bidimensional array of indices
>>> a[j]  # the same shape as `j`
array([[ 9, 16],
 [81, 49]]) 

当索引数组 a 是多维的时,单个索引数组指的是 a 的第一个维度。以下示例通过使用调色板将标签图像转换为彩色图像来展示这种行为。

>>> palette = np.array([[0, 0, 0],         # black
...                     [255, 0, 0],       # red
...                     [0, 255, 0],       # green
...                     [0, 0, 255],       # blue
...                     [255, 255, 255]])  # white
>>> image = np.array([[0, 1, 2, 0],  # each value corresponds to a color in the palette
...                   [0, 3, 4, 0]])
>>> palette[image]  # the (2, 4, 3) color image
array([[[  0,   0,   0],
 [255,   0,   0],
 [  0, 255,   0],
 [  0,   0,   0]],
 [[  0,   0,   0],
 [  0,   0, 255],
 [255, 255, 255],
 [  0,   0,   0]]]) 

我们还可以为多个维度提供索引。每个维度的索引数组必须具有相同的形状。

>>> a = np.arange(12).reshape(3, 4)
>>> a
array([[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11]])
>>> i = np.array([[0, 1],  # indices for the first dim of `a`
...               [1, 2]])
>>> j = np.array([[2, 1],  # indices for the second dim
...               [3, 3]])
>>>
>>> a[i, j]  # i and j must have equal shape
array([[ 2,  5],
 [ 7, 11]])
>>>
>>> a[i, 2]
array([[ 2,  6],
 [ 6, 10]])
>>>
>>> a[:, j]
array([[[ 2,  1],
 [ 3,  3]],
 [[ 6,  5],
 [ 7,  7]],
 [[10,  9],
 [11, 11]]]) 

在 Python 中,arr[i, j]arr[(i, j)] 完全相同—所以我们可以将 ij 放入一个 tuple 中,然后使用那个进行索引。

>>> l = (i, j)
>>> # equivalent to a[i, j]
>>> a[l]
array([[ 2,  5],
 [ 7, 11]]) 

但是,我们不能将 ij 放入数组中,因为这个数组会被解释为对 a 的第一个维度进行索引。

>>> s = np.array([i, j])
>>> # not what we want
>>> a[s]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: index 3 is out of bounds for axis 0 with size 3
>>> # same as `a[i, j]`
>>> a[tuple(s)]
array([[ 2,  5],
 [ 7, 11]]) 

使用数组进行索引的另一个常见用途是搜索时序系列的最大值:

>>> time = np.linspace(20, 145, 5)  # time scale
>>> data = np.sin(np.arange(20)).reshape(5, 4)  # 4 time-dependent series
>>> time
array([ 20\.  ,  51.25,  82.5 , 113.75, 145\.  ])
>>> data
array([[ 0\.        ,  0.84147098,  0.90929743,  0.14112001],
 [-0.7568025 , -0.95892427, -0.2794155 ,  0.6569866 ],
 [ 0.98935825,  0.41211849, -0.54402111, -0.99999021],
 [-0.53657292,  0.42016704,  0.99060736,  0.65028784],
 [-0.28790332, -0.96139749, -0.75098725,  0.14987721]])
>>> # index of the maxima for each series
>>> ind = data.argmax(axis=0)
>>> ind
array([2, 0, 3, 1])
>>> # times corresponding to the maxima
>>> time_max = time[ind]
>>>
>>> data_max = data[ind, range(data.shape[1])]  # => data[ind[0], 0], data[ind[1], 1]...
>>> time_max
array([ 82.5 ,  20\.  , 113.75,  51.25])
>>> data_max
array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
>>> np.all(data_max == data.max(axis=0))
True 

您还可以使用数组索引作为目标进行赋值:

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

然而,当索引列表包含重复时,赋值会多次进行,留下最后一个值:

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

这是合理的,但是如果你想使用 Python 的 += 构造,请注意,它可能不会产生你期望的结果:

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

即使列表中 0 出现两次,第 0 个元素也只增加了一次。这是因为 Python 要求 a += 1 等价于 a = a + 1

使用布尔数组进行索引

当我们用(整数)索引数组索引数组时,我们提供了要选择的索引列表。布尔索引的方法不同;我们明确选择要选择哪些数组项和哪些不选择。

布尔索引最自然的用法之一是使用与原始数组相同形状的布尔数组:

>>> a = np.arange(12).reshape(3, 4)
>>> b = a > 4
>>> b  # `b` is a boolean with `a`'s shape
array([[False, False, False, False],
 [False,  True,  True,  True],
 [ True,  True,  True,  True]])
>>> a[b]  # 1d array with the selected elements
array([ 5,  6,  7,  8,  9, 10, 11]) 

这个属性在赋值中非常有用:

>>> a[b] = 0  # All elements of `a` higher than 4 become 0
>>> a
array([[0, 1, 2, 3],
 [4, 0, 0, 0],
 [0, 0, 0, 0]]) 

你可以查看以下示例,了解如何使用布尔索引来生成 Mandelbrot 集合 的图像:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> def mandelbrot(h, w, maxit=20, r=2):
...  """Returns an image of the Mandelbrot fractal of size (h,w)."""
...     x = np.linspace(-2.5, 1.5, 4*h+1)
...     y = np.linspace(-1.5, 1.5, 3*w+1)
...     A, B = np.meshgrid(x, y)
...     C = A + B*1j
...     z = np.zeros_like(C)
...     divtime = maxit + np.zeros(z.shape, dtype=int)
...
...     for i in range(maxit):
...         z = z**2 + C
...         diverge = abs(z) > r                    # who is diverging
...         div_now = diverge & (divtime == maxit)  # who is diverging now
...         divtime[div_now] = i                    # note when
...         z[diverge] = r                          # avoid diverging too much
...
...     return divtime
>>> plt.clf()
>>> plt.imshow(mandelbrot(400, 400)) 

使用布尔的第二种索引方式更类似于整数索引;对于数组的每个维度,我们给出一个 1D 布尔数组,选择我们想要的切片:

>>> a = np.arange(12).reshape(3, 4)
>>> b1 = np.array([False, True, True])         # first dim selection
>>> b2 = np.array([True, False, True, False])  # second dim selection
>>>
>>> a[b1, :]                                   # selecting rows
array([[ 4,  5,  6,  7],
 [ 8,  9, 10, 11]])
>>>
>>> a[b1]                                      # same thing
array([[ 4,  5,  6,  7],
 [ 8,  9, 10, 11]])
>>>
>>> a[:, b2]                                   # selecting columns
array([[ 0,  2],
 [ 4,  6],
 [ 8, 10]])
>>>
>>> a[b1, b2]                                  # a weird thing to do
array([ 4, 10]) 

注意,1D 布尔数组的长度必须与你想要切片的维度(或轴)的长度相一致。在前面的例子中,b1 的长度为 3(a 的数量),而b2(长度为 4)适合索引a的第二个轴(列)。

ix_() 函数

ix_ 函数可以用于组合不同的向量,以便获得每个 n-uplet 的结果。例如,如果你想要计算从向量 a、b 和 c 中取出的所有三元组的 a+b*c:

>>> a = np.array([2, 3, 4, 5])
>>> b = np.array([8, 5, 4])
>>> c = np.array([5, 4, 6, 8, 3])
>>> ax, bx, cx = np.ix_(a, b, c)
>>> ax
array([[[2]],
 [[3]],
 [[4]],
 [[5]]])
>>> bx
array([[[8],
 [5],
 [4]]])
>>> cx
array([[[5, 4, 6, 8, 3]]])
>>> ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
>>> result = ax + bx * cx
>>> result
array([[[42, 34, 50, 66, 26],
 [27, 22, 32, 42, 17],
 [22, 18, 26, 34, 14]],
 [[43, 35, 51, 67, 27],
 [28, 23, 33, 43, 18],
 [23, 19, 27, 35, 15]],
 [[44, 36, 52, 68, 28],
 [29, 24, 34, 44, 19],
 [24, 20, 28, 36, 16]],
 [[45, 37, 53, 69, 29],
 [30, 25, 35, 45, 20],
 [25, 21, 29, 37, 17]]])
>>> result[3, 2, 4]
17
>>> a[3] + b[2] * c[4]

你也可以这样实现 reduce:

>>> def ufunc_reduce(ufct, *vectors):
...    vs = np.ix_(*vectors)
...    r = ufct.identity
...    for v in vs:
...        r = ufct(r, v)
...    return r 

然后将其用作:

>>> ufunc_reduce(np.add, a, b, c)
array([[[15, 14, 16, 18, 13],
 [12, 11, 13, 15, 10],
 [11, 10, 12, 14,  9]],
 [[16, 15, 17, 19, 14],
 [13, 12, 14, 16, 11],
 [12, 11, 13, 15, 10]],
 [[17, 16, 18, 20, 15],
 [14, 13, 15, 17, 12],
 [13, 12, 14, 16, 11]],
 [[18, 17, 19, 21, 16],
 [15, 14, 16, 18, 13],
 [14, 13, 15, 17, 12]]]) 

与普通的 ufunc.reduce 版本相比,这个版本的 reduce 的优势在于它利用了 广播规则 来避免创建大小为输出大小乘以向量数的参数数组。

使用字符串进行索引

参见 结构化数组。

使用索引数组进行索引

>>> a = np.arange(12)**2  # the first 12 square numbers
>>> i = np.array([1, 1, 3, 8, 5])  # an array of indices
>>> a[i]  # the elements of `a` at the positions `i`
array([ 1,  1,  9, 64, 25])
>>>
>>> j = np.array([[3, 4], [9, 7]])  # a bidimensional array of indices
>>> a[j]  # the same shape as `j`
array([[ 9, 16],
 [81, 49]]) 

当被索引的数组 a 是多维的时,单个索引数组指的是 a 的第一个维度。下面的例子通过使用调色板将标签图像转换为彩色图像来展示这种行为。

>>> palette = np.array([[0, 0, 0],         # black
...                     [255, 0, 0],       # red
...                     [0, 255, 0],       # green
...                     [0, 0, 255],       # blue
...                     [255, 255, 255]])  # white
>>> image = np.array([[0, 1, 2, 0],  # each value corresponds to a color in the palette
...                   [0, 3, 4, 0]])
>>> palette[image]  # the (2, 4, 3) color image
array([[[  0,   0,   0],
 [255,   0,   0],
 [  0, 255,   0],
 [  0,   0,   0]],
 [[  0,   0,   0],
 [  0,   0, 255],
 [255, 255, 255],
 [  0,   0,   0]]]) 

我们还可以为多个维度提供索引。每个维度的索引数组必须具有相同的形状。

>>> a = np.arange(12).reshape(3, 4)
>>> a
array([[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11]])
>>> i = np.array([[0, 1],  # indices for the first dim of `a`
...               [1, 2]])
>>> j = np.array([[2, 1],  # indices for the second dim
...               [3, 3]])
>>>
>>> a[i, j]  # i and j must have equal shape
array([[ 2,  5],
 [ 7, 11]])
>>>
>>> a[i, 2]
array([[ 2,  6],
 [ 6, 10]])
>>>
>>> a[:, j]
array([[[ 2,  1],
 [ 3,  3]],
 [[ 6,  5],
 [ 7,  7]],
 [[10,  9],
 [11, 11]]]) 

在 Python 中,arr[i, j]arr[(i, j)]完全相同—所以我们可以将ij放入一个tuple中,然后用它进行索引。

>>> l = (i, j)
>>> # equivalent to a[i, j]
>>> a[l]
array([[ 2,  5],
 [ 7, 11]]) 

然而,我们不能将ij放入一个数组中,因为这个数组将被解释为索引a的第一个维度。

>>> s = np.array([i, j])
>>> # not what we want
>>> a[s]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: index 3 is out of bounds for axis 0 with size 3
>>> # same as `a[i, j]`
>>> a[tuple(s)]
array([[ 2,  5],
 [ 7, 11]]) 

数组索引的另一个常见用途是搜索时间依赖系列的最大值:

>>> time = np.linspace(20, 145, 5)  # time scale
>>> data = np.sin(np.arange(20)).reshape(5, 4)  # 4 time-dependent series
>>> time
array([ 20\.  ,  51.25,  82.5 , 113.75, 145\.  ])
>>> data
array([[ 0\.        ,  0.84147098,  0.90929743,  0.14112001],
 [-0.7568025 , -0.95892427, -0.2794155 ,  0.6569866 ],
 [ 0.98935825,  0.41211849, -0.54402111, -0.99999021],
 [-0.53657292,  0.42016704,  0.99060736,  0.65028784],
 [-0.28790332, -0.96139749, -0.75098725,  0.14987721]])
>>> # index of the maxima for each series
>>> ind = data.argmax(axis=0)
>>> ind
array([2, 0, 3, 1])
>>> # times corresponding to the maxima
>>> time_max = time[ind]
>>>
>>> data_max = data[ind, range(data.shape[1])]  # => data[ind[0], 0], data[ind[1], 1]...
>>> time_max
array([ 82.5 ,  20\.  , 113.75,  51.25])
>>> data_max
array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
>>> np.all(data_max == data.max(axis=0))
True 

你也可以使用数组索引作为赋值的目标:

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

然而,当索引列表包含重复时,赋值会进行多次,留下最后一个值:

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

这是足够合理的,但是如果你想要使用 Python 的 += 结构,请注意,因为它可能不会产生你期望的结果:

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

尽管在索引列表中 0 出现了两次,但第 0 个元素只增加了一次。这是因为 Python 要求 a += 1 等价于 a = a + 1

使用布尔数组进行索引

当我们用 (整数) 索引数组索引数组时,我们提供了要选择的索引列表。对于布尔索引,方法是不同的;我们明确地选择我们想要的数组项和我们不想要的数组项。

布尔索引最自然的想法是使用与原始数组形状相同的布尔数组:

>>> a = np.arange(12).reshape(3, 4)
>>> b = a > 4
>>> b  # `b` is a boolean with `a`'s shape
array([[False, False, False, False],
 [False,  True,  True,  True],
 [ True,  True,  True,  True]])
>>> a[b]  # 1d array with the selected elements
array([ 5,  6,  7,  8,  9, 10, 11]) 

这个属性在赋值时非常有用:

>>> a[b] = 0  # All elements of `a` higher than 4 become 0
>>> a
array([[0, 1, 2, 3],
 [4, 0, 0, 0],
 [0, 0, 0, 0]]) 

你可以看下面的例子,看看如何使用布尔索引生成 曼德布洛特集 的图像:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> def mandelbrot(h, w, maxit=20, r=2):
...  """Returns an image of the Mandelbrot fractal of size (h,w)."""
...     x = np.linspace(-2.5, 1.5, 4*h+1)
...     y = np.linspace(-1.5, 1.5, 3*w+1)
...     A, B = np.meshgrid(x, y)
...     C = A + B*1j
...     z = np.zeros_like(C)
...     divtime = maxit + np.zeros(z.shape, dtype=int)
...
...     for i in range(maxit):
...         z = z**2 + C
...         diverge = abs(z) > r                    # who is diverging
...         div_now = diverge & (divtime == maxit)  # who is diverging now
...         divtime[div_now] = i                    # note when
...         z[diverge] = r                          # avoid diverging too much
...
...     return divtime
>>> plt.clf()
>>> plt.imshow(mandelbrot(400, 400)) 

使用布尔值进行索引的第二种方式更类似于整数索引;对于数组的每个维度,我们提供一个选择我们想要的切片的 1D 布尔数组:

>>> a = np.arange(12).reshape(3, 4)
>>> b1 = np.array([False, True, True])         # first dim selection
>>> b2 = np.array([True, False, True, False])  # second dim selection
>>>
>>> a[b1, :]                                   # selecting rows
array([[ 4,  5,  6,  7],
 [ 8,  9, 10, 11]])
>>>
>>> a[b1]                                      # same thing
array([[ 4,  5,  6,  7],
 [ 8,  9, 10, 11]])
>>>
>>> a[:, b2]                                   # selecting columns
array([[ 0,  2],
 [ 4,  6],
 [ 8, 10]])
>>>
>>> a[b1, b2]                                  # a weird thing to do
array([ 4, 10]) 

请注意,1D 布尔数组的长度必须与您要切片的维度(或轴)的长度相符。在前面的示例中,b1 的长度为 3(a 中的数),而长度为 4 的 b2 适合索引 a 的第二轴(列)。

ix_() 函数

ix_ 函数可用于组合不同向量,以便为每个 n 元组获取结果。例如,如果您想要计算所有来自向量 a、b 和 c 的三元组的 a+b*c:

>>> a = np.array([2, 3, 4, 5])
>>> b = np.array([8, 5, 4])
>>> c = np.array([5, 4, 6, 8, 3])
>>> ax, bx, cx = np.ix_(a, b, c)
>>> ax
array([[[2]],
 [[3]],
 [[4]],
 [[5]]])
>>> bx
array([[[8],
 [5],
 [4]]])
>>> cx
array([[[5, 4, 6, 8, 3]]])
>>> ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
>>> result = ax + bx * cx
>>> result
array([[[42, 34, 50, 66, 26],
 [27, 22, 32, 42, 17],
 [22, 18, 26, 34, 14]],
 [[43, 35, 51, 67, 27],
 [28, 23, 33, 43, 18],
 [23, 19, 27, 35, 15]],
 [[44, 36, 52, 68, 28],
 [29, 24, 34, 44, 19],
 [24, 20, 28, 36, 16]],
 [[45, 37, 53, 69, 29],
 [30, 25, 35, 45, 20],
 [25, 21, 29, 37, 17]]])
>>> result[3, 2, 4]
17
>>> a[3] + b[2] * c[4]
17 

您还可以这样实现 reduce:

>>> def ufunc_reduce(ufct, *vectors):
...    vs = np.ix_(*vectors)
...    r = ufct.identity
...    for v in vs:
...        r = ufct(r, v)
...    return r 

然后可如下使用它:

>>> ufunc_reduce(np.add, a, b, c)
array([[[15, 14, 16, 18, 13],
 [12, 11, 13, 15, 10],
 [11, 10, 12, 14,  9]],
 [[16, 15, 17, 19, 14],
 [13, 12, 14, 16, 11],
 [12, 11, 13, 15, 10]],
 [[17, 16, 18, 20, 15],
 [14, 13, 15, 17, 12],
 [13, 12, 14, 16, 11]],
 [[18, 17, 19, 21, 16],
 [15, 14, 16, 18, 13],
 [14, 13, 15, 17, 12]]]) 

与普通 ufunc.reduce 的这个版本相比的优势是,它利用了广播规则 以避免创建大小为输出大小乘以向量数量的参数数组。

使用字符串进行索引

参见结构化数组。

技巧和提示

这里我们提供一些简短而实用的技巧清单。

“自动”重新整形

要更改数组的尺寸,您可以省略其中一个尺寸,该尺寸将自动推导出来:

>>> a = np.arange(30)
>>> b = a.reshape((2, -1, 3))  # -1 means "whatever is needed"
>>> b.shape
(2, 5, 3)
>>> b
array([[[ 0,  1,  2],
 [ 3,  4,  5],
 [ 6,  7,  8],
 [ 9, 10, 11],
 [12, 13, 14]],
 [[15, 16, 17],
 [18, 19, 20],
 [21, 22, 23],
 [24, 25, 26],
 [27, 28, 29]]]) 

向量叠加

如何从等尺寸行向量列表构建二维数组?在 MATLAB 中,这很容易:如果 xy 是两个相同长度的向量,则只需进行 m=[x;y]。在 NumPy 中,这可以通过函数 column_stackdstackhstackvstack 来实现,具体取决于要执行叠加的维度。例如:

>>> x = np.arange(0, 10, 2)
>>> y = np.arange(5)
>>> m = np.vstack([x, y])
>>> m
array([[0, 2, 4, 6, 8],
 [0, 1, 2, 3, 4]])
>>> xy = np.hstack([x, y])
>>> xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4]) 

那些超过两维的函数背后的逻辑可能会有些奇怪。

请参阅

面向 MATLAB 用户的 NumPy

直方图

应用于数组的 NumPy histogram 函数返回一个向量对:数组的直方图和一个箱边向量。注意:matplotlib 也有一个构建直方图的函数(称为 hist,类似于 Matlab 中的),与 NumPy 中的函数不同。主要区别在于,pylab.hist 会自动绘制直方图,而 numpy.histogram 只生成数据。

>>> import numpy as np
>>> rg = np.random.default_rng(1)
>>> import matplotlib.pyplot as plt
>>> # Build a vector of 10000 normal deviates with variance 0.5² and mean 2
>>> mu, sigma = 2, 0.5
>>> v = rg.normal(mu, sigma, 10000)
>>> # Plot a normalized histogram with 50 bins
>>> plt.hist(v, bins=50, density=True)       # matplotlib version (plot)
(array...)
>>> # Compute the histogram with numpy and then plot it
>>> (n, bins) = np.histogram(v, bins=50, density=True)  # NumPy version (no plot)
>>> plt.plot(.5 * (bins[1:] + bins[:-1]), n) 

对于 Matplotlib >=3.4,您也可以使用 plt.stairs(n, bins)

“自动”重新整形

要更改数组的尺寸,您可以省略其中一个尺寸,该尺寸将自动推导出来:

>>> a = np.arange(30)
>>> b = a.reshape((2, -1, 3))  # -1 means "whatever is needed"
>>> b.shape
(2, 5, 3)
>>> b
array([[[ 0,  1,  2],
 [ 3,  4,  5],
 [ 6,  7,  8],
 [ 9, 10, 11],
 [12, 13, 14]],
 [[15, 16, 17],
 [18, 19, 20],
 [21, 22, 23],
 [24, 25, 26],
 [27, 28, 29]]]) 

向量叠加

如何从等尺寸行向量列表构建二维数组?在 MATLAB 中,这很容易:如果 xy 是两个相同长度的向量,则只需进行 m=[x;y]。在 NumPy 中,这可以通过函数 column_stackdstackhstackvstack 来实现,具体取决于要执行叠加的维度。例如:

>>> x = np.arange(0, 10, 2)
>>> y = np.arange(5)
>>> m = np.vstack([x, y])
>>> m
array([[0, 2, 4, 6, 8],
 [0, 1, 2, 3, 4]])
>>> xy = np.hstack([x, y])
>>> xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4]) 

针对超过两维的函数背后的逻辑可能会有些奇怪。

请参阅

面向 MATLAB 用户的 NumPy

直方图

应用于数组的 NumPy histogram 函数返回一对向量:数组的直方图和一个边界向量。注意:matplotlib 也有一个构建直方图的函数(称为 hist,就像 Matlab 中的一样),它与 NumPy 中的不同。主要区别在于 pylab.hist 会自动绘制直方图,而 numpy.histogram 只会生成数据。

>>> import numpy as np
>>> rg = np.random.default_rng(1)
>>> import matplotlib.pyplot as plt
>>> # Build a vector of 10000 normal deviates with variance 0.5² and mean 2
>>> mu, sigma = 2, 0.5
>>> v = rg.normal(mu, sigma, 10000)
>>> # Plot a normalized histogram with 50 bins
>>> plt.hist(v, bins=50, density=True)       # matplotlib version (plot)
(array...)
>>> # Compute the histogram with numpy and then plot it
>>> (n, bins) = np.histogram(v, bins=50, density=True)  # NumPy version (no plot)
>>> plt.plot(.5 * (bins[1:] + bins[:-1]), n) 

在 Matplotlib >=3.4 中,你也可以使用 plt.stairs(n, bins)

进一步阅读

相关文章
|
7月前
|
Python
NumPy 1.26 中文官方指南(五)
NumPy 1.26 中文官方指南(五)
56 1
|
7月前
|
BI 索引 Python
NumPy 1.26 中文官方指南(一)(2)
NumPy 1.26 中文官方指南(一)
105 1
NumPy 1.26 中文官方指南(一)(2)
|
7月前
|
存储 BI 索引
NumPy 1.26 中文官方指南(一)(3)
NumPy 1.26 中文官方指南(一)
54 1
|
7月前
|
存储 程序员 BI
NumPy 1.26 中文官方指南(一)(1)
NumPy 1.26 中文官方指南(一)
82 1
|
7月前
|
存储 程序员 API
NumPy 1.26 中文官方指南(四)(1)
NumPy 1.26 中文官方指南(四)
59 1
|
7月前
|
并行计算 PyTorch 算法框架/工具
NumPy 1.26 中文官方指南(三)(4)
NumPy 1.26 中文官方指南(三)
130 1
|
7月前
|
编译器 C语言 C++
NumPy 1.26 中文官方指南(三)(2)
NumPy 1.26 中文官方指南(三)
103 1
|
7月前
|
存储 数据建模 索引
NumPy 1.26 中文官方指南(三)(1)
NumPy 1.26 中文官方指南(三)
89 1
|
7月前
|
机器学习/深度学习 存储 数据可视化
NumPy 1.26 中文官方指南(二)(4)
NumPy 1.26 中文官方指南(二)
109 1
|
7月前
|
存储 数据可视化 数据挖掘
NumPy 1.26 中文官方指南(二)(2)
NumPy 1.26 中文官方指南(二)
126 0