目录

NumPy ndarray:多维数组对象创建 ndarraysndarrays 的数据类型使用 NumPy 数组进行运算基本索引和切片使用切片编制索引

布尔索引花式索引转置数组和交换轴

伪随机数生成通用函数:快速的逐元素数组函数数组面向数组编程将条件逻辑表示为数组运算数学和统计方法布尔数组的方法排序唯一和其他集合逻辑

使用数组进行文件输入和输出线性代数随机游走

NumPy ndarray:多维数组对象

NumPy 的主要功能之一是它的 N 维数组对象或 ndarray,它是 Python 中大型数据集的快速、灵活的容器。数组使您能够使用与标量元素之间的等效运算类似的语法对整个数据块执行数学运算。

为了让您了解 NumPy 如何启用与内置 Python 对象上的标量值语法相似的批处理计算,我首先导入 NumPy 并创建一个小型数组:

In [12]: import numpy as np

In [13]: data = np.array([[1.5, -0.1, 3], [0, -3, 6.5]])

In [14]: data

Out[14]:

array([[ 1.5, -0.1, 3. ],

[ 0. , -3. , 6.5]])

然后我用以下语言编写数学运算:data

In [15]: data * 10

Out[15]:

array([[ 15., -1., 30.],

[ 0., -30., 65.]])

In [16]: data + data

Out[16]:

array([[ 3. , -0.2, 6. ],

[ 0. , -6. , 13. ]])

在第一个示例中,所有元素都乘以 10。在第二种情况下,数组中每个“单元格”中的相应值已相互相加。 ndarray 是用于同构数据的通用多维容器;也就是说,所有元素必须是相同的类型。每个数组都有一个 ,一个表示每个维度大小的元组,以及一个描述数组数据类型的对象:shape dtype

In [17]: data.shape

Out[17]: (2, 3)

In [18]: data.dtype

Out[18]: dtype('float64')

创建 ndarrays

创建数组的最简单方法是使用该函数。这接受任何类似序列的对象(包括其他数组),并生成包含传递数据的新 NumPy 数组。

In [19]: data1 = [6, 7.5, 8, 0, 1]

In [20]: arr1 = np.array(data1)

In [21]: arr1

Out[21]: array([6. , 7.5, 8. , 0. , 1. ])

嵌套序列,如等长列表列表,将被转换为多维数组:

In [22]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]

In [23]: arr2 = np.array(data2)

In [24]: arr2

Out[24]:

array([[1, 2, 3, 4],

[5, 6, 7, 8]])

由于是列表,因此 NumPy 数组具有两个维度,从数据推断出形状。我们可以通过检查属性来确认这一点:arr2.ndim arr2.shape

In [25]: arr2.ndim

Out[25]: 2

In [26]: arr2.shape

Out[26]: (2, 4)

除非显式指定,否则会尝试为其创建的数组推断出良好的数据类型。数据类型存储在特殊的元数据对象中;例如,在前两个示例中,我们有:numpy.array dtype

In [27]: arr1.dtype

Out[27]: dtype('float64')

In [28]: arr2.dtype

Out[28]: dtype('int64')

除此之外,还有许多其他函数用于创建新数组。例如,分别创建具有给定长度或形状的 0 或 1 数组。 创建一个数组,而不将其值初始化为任何特定值。若要使用这些方法创建更高维数组,请传递具有形状的元组:numpy.array numpy.zeros numpy.ones numpy.empty

In [29]: np.zeros(10)

Out[29]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

In [30]: np.zeros((3, 6))

Out[30]:

array([[0., 0., 0., 0., 0., 0.],

[0., 0., 0., 0., 0., 0.],

[0., 0., 0., 0., 0., 0.]])

In [31]: np.empty((2, 3, 2))

Out[31]:

array([[[0., 0.],

[0., 0.],

[0., 0.]],

[[0., 0.],

[0., 0.],

[0., 0.]]])

假设这将返回一个包含所有零的数组是不安全的。此函数返回未初始化的内存,因此可能包含非零的“垃圾”值。仅当您打算用数据填充新数组时,才应使用此函数。numpy.empty

numpy.arange是内置 Python 函数: range的数组值版本

In [32]: np.arange(15)

Out[32]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

由于 NumPy 专注于数值计算,因此如果未指定数据类型,则在许多情况下将为(浮点数)float64

一些重要的 NumPy 数组创建函数

函数描述array通过推断数据类型或显式指定数据类型,将输入数据(列表、元组、数组或其他序列类型)转换为 ndarray;默认情况下复制输入数据asarray将输入转换为 ndarray,但如果输入已经是 ndarray,则不要复制arange像内置的一样,但返回一个 ndarray 而不是一个列表 rangeones, ones_like生成一个包含所有 1 的数组,具有给定的形状和数据类型; 获取另一个数组并生成相同形状和数据类型的数组 ones_like oneszeros, zeros_like像ones, ones_like函数一样,但生成值是0的数组empty, empty_like通过分配新内存创建新数组,但不要填充任何值,如ones zerosfull, full_like生成给定形状和数据类型的数组,所有值都设置为指示的“填充值”; 获取另一个数组并生成相同形状和数据类型的填充数组full_likeeye, identity创建一个正方形 N × N 单位矩阵(对角线上为 1,其他地方为 0

ndarrays 的数据类型

数据类型 or 是一个特殊对象,其中包含 ndarray 将内存块解释为特定类型的数据所需的信息(或元数据、有关数据的数据):dtype

In [33]: arr1 = np.array([1, 2, 3], dtype=np.float64)

In [34]: arr2 = np.array([1, 2, 3], dtype=np.int32)

In [35]: arr1.dtype

Out[35]: dtype('float64')

In [36]: arr2.dtype

Out[36]: dtype('int32')

数据类型是NumPy与来自其他系统的数据交互的灵活性的来源。在大多数情况下,它们直接提供到底层磁盘或内存表示的映射,从而可以在磁盘上读取和写入二进制数据流,并连接到用C或FORTRAN等低级语言编写的代码。数字数据类型的命名方式相同:类型名,如或,后跟表示每个元素位数的数字。一个标准的双精度浮点值(Python对象中隐藏使用的值)占用8个字节或64位。因此,这种类型在NumPy中被广泛所知。

类型类型代码描述int8, uint8i1, u1有符号和无符号 8 位(1 字节)整数类型int16, uint16i2, u2有符号和无符号 16 位整数类型int32, uint32i4, u4有符号和无符号的 32 位整数类型int64, uint64i8, u8有符号和无符号 64 位整数类型float16f2半精度浮点float32f4 or f标准单精度浮点数;兼容 C 浮点数float64f8 or d标准双精度浮点;兼容 C double 和 Python 对象floatfloat128f16 or g扩展精度浮点complex64, complex128, complex256c8, c16, c32分别由两个 32、64 或 128 浮点数表示的复数bool?布尔类型存储和值True FalseobjectOPython 对象类型;值可以是任何 Python 对象string_S固定长度的 ASCII 字符串类型(每个字符 1 个字节);例如,若要创建长度为 10 的字符串数据类型,请使用‘S10’unicode_U固定长度的 Unicode 类型(特定于平台的字节数);与(例如,string_‘U10’)

有符号整数可以表示正整数和负整数,而无符号整数只能表示非零整数。例如,(有符号的 8 位整数)可以表示从 -128 到 127(含)的整数,而(无符号的 8 位整数)可以表示 0 到 255。int8 uint8

使用 ndarray 的方法将数组从一种数据类型显式转换或强制转换为另一种数据类型:astype

In [37]: arr = np.array([1, 2, 3, 4, 5])

In [38]: arr.dtype

Out[38]: dtype('int64')

In [39]: float_arr = arr.astype(np.float64)

In [40]: float_arr

Out[40]: array([1., 2., 3., 4., 5.])

In [41]: float_arr.dtype

Out[41]: dtype('float64')

在此示例中,整数被强制转换为浮点数。如果我将一些浮点数转换为整数数据类型,则小数部分将被截断:

In [42]: arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])

In [43]: arr

Out[43]: array([ 3.7, -1.2, -2.6, 0.5, 12.9, 10.1])

In [44]: arr.astype(np.int32)

Out[44]: array([ 3, -1, -2, 0, 12, 10], dtype=int32)

如果有一个表示数字的字符串数组,则可以使用它们转换为数字形式:astype

In [45]: numeric_strings = np.array(["1.25", "-9.6", "42"], dtype=np.string_)

In [46]: numeric_strings.astype(float)

Out[46]: array([ 1.25, -9.6 , 42. ])

NumPy 中的字符串数据是固定大小的,可能会在没有警告的情况下截断输入。Pandas在非数字数据上具有更直观的开箱即用行为。numpy.string_

由于某种原因(如无法转换为的字符串)可能导致强制转换失败,NumPy将Python类型别名为自己的等效数据类型。float64 ValueError float np.float64 您还可以使用另一个数组的属性:dtype

In [47]: int_array = np.arange(10)

In [48]: calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)

In [49]: int_array.astype(calibers.dtype)

Out[49]: array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

还有一些速记类型的代码字符串,你也可以用它来指代一个:dtype

In [50]: zeros_uint32 = np.zeros(8, dtype="u4")

In [51]: zeros_uint32

Out[51]: array([0, 0, 0, 0, 0, 0, 0, 0], dtype=uint32)

调用始终会创建一个新数组(数据的副本),即使新数据类型与旧数据类型相同也是如此。astype

使用 NumPy 数组进行运算

数组能够在不写入任何循环的情况下对数据进行批处理操作,称之为矢量化。等大小数组之间的任何算术运算都按元素应用运算:for

In [52]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])

In [53]: arr

Out[53]:

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

[4., 5., 6.]])

In [54]: arr * arr

Out[54]:

array([[ 1., 4., 9.],

[16., 25., 36.]])

In [55]: arr - arr

Out[55]:

array([[0., 0., 0.],

[0., 0., 0.]])

使用标量的算术运算将标量参数传播到数组中的每个元素:

In [56]: 1 / arr

Out[56]:

array([[1. , 0.5 , 0.3333],

[0.25 , 0.2 , 0.1667]])

In [57]: arr ** 2

Out[57]:

array([[ 1., 4., 9.],

[16., 25., 36.]])

相同大小的数组之间的比较产生布尔数组:

In [58]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])

In [59]: arr2

Out[59]:

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

[ 7., 2., 12.]])

In [60]: arr2 > arr

Out[60]:

array([[False, True, False],

[ True, False, True]])

评估不同大小的数组之间的操作称为broadcasting,更多细节见NumPy 高级应用:数组算法与函数应用。

基本索引和切片

NumPy 数组索引可以通过多种方式选择数据的子集或单个元素。一维数组很简单;从表面上看,它们的行为类似于 Python 列表:

In [61]: arr = np.arange(10)

In [62]: arr

Out[62]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [63]: arr[5]

Out[63]: 5

In [64]: arr[5:8]

Out[64]: array([5, 6, 7])

In [65]: arr[5:8] = 12

In [66]: arr

Out[66]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])

如果将标量值分配给切片,则该值将传播、应用到整个选择 arr[5:8] = 12

与 Python 内置列表的第一个重要区别是数组切片是原始数组上的视图。这意味着不会复制数据,并且对视图的任何修改都将反映在源数组中。

举个例子,首先创建一个切片:arr

In [67]: arr_slice = arr[5:8]

In [68]: arr_slice

Out[68]: array([12, 12, 12])

现在,当更改 arr_slice中的值时,突变会反映在原始数组中:arr_slice arr

In [69]: arr_slice[1] = 12345

In [70]: arr

Out[70]:

array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,

9])

“裸”切片将分配给数组中的所有值:[:]

In [71]: arr_slice[:] = 64

In [72]: arr

Out[72]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])

使用更高维的数组,有更多的选择。在二维数组中,每个索引处的元素不再是标量,而是一维数组:

In [73]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

In [74]: arr2d[2]

Out[74]: array([7, 8, 9])

因此,可以递归访问单个元素。但这有点太多了,所以你可以传递一个逗号分隔的索引列表来选择单个元素。所以这些是等价的:

In [75]: arr2d[0][2]

Out[75]: 3

In [76]: arr2d[0, 2]

Out[76]: 3

有关二维数组索引的图示,将轴 0 视为数组的“行”,将轴 1 视为“列”。 在多维数组中,如果省略后面的索引,则返回的对象将是一个低维 ndarray,由沿高维的所有数据组成。所以在 2 × 2 × 3 数组中:arr3d

In [77]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])

In [78]: arr3d

Out[78]:

array([[[ 1, 2, 3],

[ 4, 5, 6]],

[[ 7, 8, 9],

[10, 11, 12]]])

arr3d[0]是一个 2 × 3 数组:

In [79]: arr3d[0]

Out[79]:

array([[1, 2, 3],

[4, 5, 6]])

标量值和数组都可以分配给:arr3d[0]

In [80]: old_values = arr3d[0].copy()

In [81]: arr3d[0] = 42

In [82]: arr3d

Out[82]:

array([[[42, 42, 42],

[42, 42, 42]],

[[ 7, 8, 9],

[10, 11, 12]]])

In [83]: arr3d[0] = old_values

In [84]: arr3d

Out[84]:

array([[[ 1, 2, 3],

[ 4, 5, 6]],

[[ 7, 8, 9],

[10, 11, 12]]])

类似地,为您提供索引以 开头的所有值,形成一个一维数组:arr3d [1, 0] (1, 0)

In [85]: arr3d[1, 0]

Out[85]: array([7, 8, 9])

此表达式与我们分两步编制索引的表达式相同:

In [86]: x = arr3d[1]

In [87]: x

Out[87]:

array([[ 7, 8, 9],

[10, 11, 12]])

In [88]: x[0]

Out[88]: array([7, 8, 9])

请注意,在所有这些情况下,如果选择了数组的子部分,则返回的数组都是视图。

NumPy 数组的这种多维索引语法不适用于常规 Python 对象,例如列表

使用切片编制索引

与一维对象(如 Python 列表)一样,ndarrays 可以使用熟悉的语法进行切片:

In [89]: arr

Out[89]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])

In [90]: arr[1:6]

Out[90]: array([ 1, 2, 3, 4, 64])

考虑前面的二维数组。对这个数组进行切片有点不同:arr2d

In [91]: arr2d

Out[91]:

array([[1, 2, 3],

[4, 5, 6],

[7, 8, 9]])

In [92]: arr2d[:2]

Out[92]:

array([[1, 2, 3],

[4, 5, 6]])

如您所见,它已沿轴 0(第一个轴)切片。因此,切片沿轴选择一系列元素。将表达式读作“选择的前两行”。arr2d[:2] arr2d 您可以传递多个切片,就像您可以传递多个索引一样:

In [93]: arr2d[:2, 1:]

Out[93]:

array([[2, 3],

[5, 6]])

像这样切片时,您始终会获得相同维度数的数组视图。通过混合整数索引和切片,可以得到低维切片。

例如,我可以选择第二行,但只能选择前两列,如下所示:

In [94]: lower_dim_slice = arr2d[1, :2]

这里,虽然是二维的,但也是一维的,它的形状是一个轴大小为一个元组:arr2d lower_dim_slice

In [95]: lower_dim_slice.shape

Out[95]: (2,)

同样,我可以选择第三列,但只能选择前两行,如下所示:

In [96]: arr2d[:2, 2]

Out[96]: array([3, 6])

冒号本身意味着采用整个轴,因此您可以通过以下操作仅对更高维的轴进行切片:

In [97]: arr2d[:, :1]

Out[97]:

array([[1],

[4],

[7]])

当然,赋值给切片表达式会赋值给整个选择:

In [98]: arr2d[:2, 1:] = 0

In [99]: arr2d

Out[99]:

array([[1, 0, 0],

[4, 0, 0],

[7, 8, 9]])

布尔索引

让我们考虑一个例子,在这个例子中,我们在一个数组和一个具有重复项的名称数组中有一些数据:

In [100]: names = np.array(["Bob", "Joe", "Will", "Bob", "Will", "Joe", "Joe"])

In [101]: data = np.array([[4, 7], [0, 2], [-5, 6], [0, 0], [1, 2],

.....: [-12, -4], [3, 4]])

In [102]: names

Out[102]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='

In [103]: data

Out[103]:

array([[ 4, 7],

[ 0, 2],

[ -5, 6],

[ 0, 0],

[ 1, 2],

[-12, -4],

[ 3, 4]])

假设每个名称对应于数组中的一行,并且我们希望选择具有相应名称的所有行。与算术运算一样,与数组的比较(如)也被矢量化。因此,与字符串进行比较会产生一个布尔数组:data"Bob"==names"Bob"

In [104]: names == "Bob"

Out[104]: array([ True, False, False, True, False, False, False])

索引数组时可以传递此布尔数组:

In [105]: data[names == "Bob"]

Out[105]:

array([[4, 7],

[0, 0]])

布尔数组的长度必须与其索引的数组轴的长度相同。您甚至可以将布尔数组与切片或整数(或整数序列;稍后会详细介绍)混合匹配。 在这些示例中,我从其中的行中进行选择,并对列进行索引:names==“Bob”

In [106]: data[names == "Bob", 1:]

Out[106]:

array([[7],

[0]])

In [107]: data[names == "Bob", 1]

Out[107]: array([7, 0])

要选择所有内容,但您可以使用以下命令使用或否定条件:“Bob” != ~

In [108]: names != "Bob"

Out[108]: array([False, True, True, False, True, True, True])

In [109]: ~(names == "Bob")

Out[109]: array([False, True, True, False, True, True, True])

In [110]: data[~(names == "Bob")]

Out[110]:

array([[ 0, 2],

[ -5, 6],

[ 1, 2],

[-12, -4],

[ 3, 4]])

当您想要反转由变量引用的布尔数组时,运算符可能很有用:~

In [111]: cond = names == "Bob"

In [112]: data[~cond]

Out[112]:

array([[ 0, 2],

[ -5, 6],

[ 1, 2],

[-12, -4],

[ 3, 4]])

若要从三个名称中选择两个来组合多个布尔条件,请使用布尔算术运算符,如 (and) 和 (or):& |

In [113]: mask = (names == "Bob") | (names == "Will")

In [114]: mask

Out[114]: array([ True, False, True, True, True, False, False])

In [115]: data[mask]

Out[115]:

array([[ 4, 7],

[-5, 6],

[ 0, 0],

[ 1, 2]])

通过布尔索引从数组中选择数据并将结果分配给新变量始终会创建数据的副本,即使返回的数组未更改也是如此。

Python 关键字 和 不适用于布尔数组。请改用 (and) 和 (or)。and or & |

使用布尔数组设置值的工作原理是将右侧的一个或多个值代入布尔数组的值所在的位置。要将所有负值设置为 0,我们只需要执行以下操作:True data

In [116]: data[data < 0] = 0

In [117]: data

Out[117]:

array([[4, 7],

[0, 2],

[0, 6],

[0, 0],

[1, 2],

[0, 0],

[3, 4]])

您还可以使用一维布尔数组设置整行或整列:

In [118]: data[names != "Joe"] = 7

In [119]: data

Out[119]:

array([[7, 7],

[0, 2],

[7, 7],

[7, 7],

[7, 7],

[0, 0],

[3, 4]])

正如我们稍后将看到的,这些类型的二维数据操作对于pandas来说很方便。

花式索引

花式索引是 NumPy 采用的一个术语,用于描述使用整数数组的索引。假设我们有一个 8 × 4 数组:

In [120]: arr = np.zeros((8, 4))

In [121]: for i in range(8):

.....: arr[i] = i

In [122]: arr

Out[122]:

array([[0., 0., 0., 0.],

[1., 1., 1., 1.],

[2., 2., 2., 2.],

[3., 3., 3., 3.],

[4., 4., 4., 4.],

[5., 5., 5., 5.],

[6., 6., 6., 6.],

[7., 7., 7., 7.]])

要按特定顺序选择行的子集,只需传递指定所需顺序的整数列表或 ndarray 即可:

In [123]: arr[[4, 3, 0, 6]]

Out[123]:

array([[4., 4., 4., 4.],

[3., 3., 3., 3.],

[0., 0., 0., 0.],

[6., 6., 6., 6.]])

希望这段代码能达到你的预期!使用负索引从末尾选择行:

In [124]: arr[[-3, -5, -7]]

Out[124]:

array([[5., 5., 5., 5.],

[3., 3., 3., 3.],

[1., 1., 1., 1.]])

传递多个索引数组会做一些稍微不同的事情;它选择对应于每个索引元组的一维元素数组:

In [125]: arr = np.arange(32).reshape((8, 4))

In [126]: arr

Out[126]:

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, 30, 31]])

In [127]: arr[[1, 5, 7, 2], [0, 3, 1, 2]]

Out[127]: array([ 4, 23, 29, 10])

这里选择了元素,并被选中。使用与轴一样多的整数数组进行花式索引的结果始终是一维的。(1, 0), (5, 3), (7, 1) (2, 2) 在这种情况下,花式索引的行为与某些用户的预期略有不同,后者是通过选择矩阵的行和列的子集形成的矩形区域。这是获得此目的的一种方法:

In [128]: arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]

Out[128]:

array([[ 4, 7, 5, 6],

[20, 23, 21, 22],

[28, 31, 29, 30],

[ 8, 11, 9, 10]])

请记住,与切片不同,花式索引在将结果分配给新变量时总是将数据复制到新数组中。如果使用花式索引来分配值,则将修改索引值:

In [129]: arr[[1, 5, 7, 2], [0, 3, 1, 2]]

Out[129]: array([ 4, 23, 29, 10])

In [130]: arr[[1, 5, 7, 2], [0, 3, 1, 2]] = 0

In [131]: arr

Out[131]:

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

[ 0, 5, 6, 7],

[ 8, 9, 0, 11],

[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 0],

[24, 25, 26, 27],

[28, 0, 30, 31]])

转置数组和交换轴

转置是一种特殊的重塑形式,它同样在不复制任何内容的情况下返回底层数据的视图。数组具有方法和特殊属性:transpose T

In [132]: arr = np.arange(15).reshape((3, 5))

In [133]: arr

Out[133]:

array([[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]])

In [134]: arr.T

Out[134]:

array([[ 0, 5, 10],

[ 1, 6, 11],

[ 2, 7, 12],

[ 3, 8, 13],

[ 4, 9, 14]])

在进行矩阵计算时,您可能会经常这样做,例如,在使用以下方法计算内矩阵乘积时:numpy.dot

In [135]: arr = np.array([[0, 1, 0], [1, 2, -2], [6, 3, 2], [-1, 0, -1], [1, 0, 1

]])

In [136]: arr

Out[136]:

array([[ 0, 1, 0],

[ 1, 2, -2],

[ 6, 3, 2],

[-1, 0, -1],

[ 1, 0, 1]])

In [137]: np.dot(arr.T, arr)

Out[137]:

array([[39, 20, 12],

[20, 14, 2],

[12, 2, 10]])

中缀运算符是执行矩阵乘法的另一种方法:@

In [138]: arr.T @ arr

Out[138]:

array([[39, 20, 12],

[20, 14, 2],

[12, 2, 10]])

简单的转置是交换轴的特殊情况。 ndarray具有方法,该方法采用一对轴编号,并切换指示的轴以重新排列数据:.T swapaxes

In [139]: arr

Out[139]:

array([[ 0, 1, 0],

[ 1, 2, -2],

[ 6, 3, 2],

[-1, 0, -1],

[ 1, 0, 1]])

In [140]: arr.swapaxes(0, 1)

Out[140]:

array([[ 0, 1, 6, -1, 1],

[ 1, 2, 3, 0, 0],

[ 0, -2, 2, -1, 1]])

swapaxes同样,它返回数据视图,而不进行复制。

伪随机数生成

该模块补充了内置的 Python 模块,其中包含用于从多种概率分布中有效生成整个样本值数组的函数。例如,您可以使用以下方法从标准正态分布中获取 4 × 4 个样本数组:numpy.random random numpy.random.standard_normal

In [141]: samples = np.random.standard_normal(size=(4, 4))

In [142]: samples

Out[142]:

array([[-0.2047, 0.4789, -0.5194, -0.5557],

[ 1.9658, 1.3934, 0.0929, 0.2817],

[ 0.769 , 1.2464, 1.0072, -1.2962],

[ 0.275 , 0.2289, 1.3529, 0.8864]])

相比之下,Python 的内置模块一次只采样一个值。从这个基准测试中可以看出,对于生成非常大的样本来说,速度要快一个数量级以上:random numpy.random

In [143]: from random import normalvariate

In [144]: N = 1_000_000

In [145]: %timeit samples = [normalvariate(0, 1) for _ in range(N)]

490 ms +- 2.23 ms per loop (mean +- std. dev. of 7 runs, 1 loop each)

In [146]: %timeit np.random.standard_normal(N)

32.6 ms +- 271 us per loop (mean +- std. dev. of 7 runs, 10 loops each)

这些随机数不是真正的随机数(更确切地说是伪随机数),而是由可配置的随机数生成器生成的,该随机数生成器确定创建的值。函数,例如使用模块的默认随机数生成器,但可以将代码配置为使用显式生成器:numpy.random.standard_normal numpy.random

In [147]: rng = np.random.default_rng(seed=12345)

In [148]: data = rng.standard_normal((2, 3))

参数决定了生成器的初始状态,每次使用对象生成数据时,状态都会发生变化。生成器对象也与可能使用该模块的其他代码隔离:seed rng rng numpy.random

In [149]: type(rng)

Out[149]: numpy.random._generator.Generator

随机生成器对象上可用的部分方法列表

NumPy 随机数生成器方法

方法描述permutation返回序列的随机排列,或返回排列范围shuffle随机置换序列uniform从均匀分布中抽取样本integers从给定的从低到高范围绘制随机整数standard_normal从均值为 0、标准差为 1 的正态分布中抽取样本binomial从二项分布中抽取样本normal从正态(高斯)分布中抽取样本beta从 beta 分布中抽取样本chisquare从卡方分布中抽取样本gamma从 gamma 分布中抽取样本uniform从均匀的 [ 0,1)分布中抽取样本

通用函数:快速的逐元素数组函数

通用函数 (ufunc) 是对 ndarray 中的数据执行元素级运算的函数。您可以将它们视为简单函数的快速矢量化包装器,这些函数采用一个或多个标量值并生成一个或多个标量结果。 许多 ufunc 都是简单的元素转换,例如 或:numpy.sqrt numpy.exp

In [150]: arr = np.arange(10)

In [151]: arr

Out[151]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [152]: np.sqrt(arr)

Out[152]:

array([0. , 1. , 1.4142, 1.7321, 2. , 2.2361, 2.4495, 2.6458,

2.8284, 3. ])

In [153]: np.exp(arr)

Out[153]:

array([ 1. , 2.7183, 7.3891, 20.0855, 54.5982, 148.4132,

403.4288, 1096.6332, 2980.958 , 8103.0839])

这些被称为一元 ufunc。其他的,如采用两个数组(因此是二进制 ufunc)并返回一个数组作为结果:numpy.add numpy.maximum

In [154]: x = rng.standard_normal(8)

In [155]: y = rng.standard_normal(8)

In [156]: x

Out[156]:

array([-1.3678, 0.6489, 0.3611, -1.9529, 2.3474, 0.9685, -0.7594,

0.9022])

In [157]: y

Out[157]:

array([-0.467 , -0.0607, 0.7888, -1.2567, 0.5759, 1.399 , 1.3223,

-0.2997])

In [158]: np.maximum(x, y)

Out[158]:

array([-0.467 , 0.6489, 0.7888, -1.2567, 2.3474, 1.399 , 1.3223,

0.9022])

在本例中,计算了 .numpy.maximum x y 中元素的元素最大值 虽然不常见,但一个 ufunc 可以返回多个数组。一个例子:内置Python的矢量化版本,它返回浮点数组的小数和整数部分:numpy.modf math.modf

In [159]: arr = rng.standard_normal(7) * 5

In [160]: arr

Out[160]: array([ 4.5146, -8.1079, -0.7909, 2.2474, -6.718 , -0.4084, 8.6237])

In [161]: remainder, whole_part = np.modf(arr)

In [162]: remainder

Out[162]: array([ 0.5146, -0.1079, -0.7909, 0.2474, -0.718 , -0.4084, 0.6237])

In [163]: whole_part

Out[163]: array([ 4., -8., -0., 2., -6., -0., 8.])

Ufuncs 接受一个可选参数,该参数允许它们将结果分配到现有数组中,而不是创建一个新数组:out

In [164]: arr

Out[164]: array([ 4.5146, -8.1079, -0.7909, 2.2474, -6.718 , -0.4084, 8.6237])

In [165]: out = np.zeros_like(arr)

In [166]: np.add(arr, 1)

Out[166]: array([ 5.5146, -7.1079, 0.2091, 3.2474, -5.718 , 0.5916, 9.6237])

In [167]: np.add(arr, 1, out=out)

Out[167]: array([ 5.5146, -7.1079, 0.2091, 3.2474, -5.718 , 0.5916, 9.6237])

In [168]: out

Out[168]: array([ 5.5146, -7.1079, 0.2091, 3.2474, -5.718 , 0.5916, 9.6237])

一些一元通用函数

方法描述abs, fabs按元素计算整数、浮点值或复数值的绝对值sqrt计算每个元素的平方根(等于arr ** 0.5)square计算每个元素的平方(相当于arr ** 2)exp计算指数 ex 每个元素log, log10, log2, log1p自然对数(以 e 为基数)、对数以 10 为基数、以 2 为基数的对数和 log(1 + x)sign计算每个元素的符号:1(正)、0(零)或 –1(负)ceil计算每个元素的上限(即大于或等于该数字的最小整数)floor计算每个元素的下限(即小于或等于每个元素的最大整数)rint将元素舍入到最接近的整数,保留 dtypemodf将数组的小数部分和整数部分作为单独的数组返回isnan返回指示每个值是否为 (Not a Number) 的布尔数组 NaNisfinite, isinf返回布尔数组,分别指示每个元素是有限的(非、非)还是无限的 inf NaNcos, cosh, sin, sinh, tan, tanh正则三角函数和双曲三角函数arccos, arccosh, arcsin, arcsinh, arctan, arctanh反三角函数logical_not逐个元素计算真值(相当于not x ~arr)

一些二进制通用函数

方法描述add在数组中添加相应的元素subtract从第一个数组中减去第二个数组中的元素multiply乘以数组元素divide, floor_divide分隔或地板分隔(截断余数)power将第一个数组中的元素提升到第二个数组中指示的幂maximum, fmax元素最大值; 忽略fmax NaNminimum, fmin元素最小值; 忽略fmin NaNmod元素比率(除法余数)copysign将第二个参数中的值符号复制到第一个参数中的值greater, greater_equal, less, less_equal, equal, not_equal执行元素比较,生成布尔数组(相当于中缀运算符 >, >=, <, <=, ==, != )logical_and计算 AND () 逻辑运算的元素真值 &logical_or计算 OR () 逻辑运算的元素真值 |logical_xor计算 XOR () 逻辑运算的元素真值 ^

数组面向数组编程

使用 NumPy 数组,可以将多种数据处理任务表示为简洁的数组表达式,否则可能需要写入循环。这种用数组表达式替换显式循环的做法被一些人称为向量化。一般来说,矢量化数组运算通常比纯Python运算快得多,在任何类型的数值计算中影响最大。

作为一个简单的例子,假设我们希望通过一个规则的值网格来评估函数。该函数采用两个一维数组,并生成两个二维矩阵,对应于这两个数组中的所有对:lsqrt(x^2 + y^2) numpy.meshgrid (x, y)

In [169]: points = np.arange(-5, 5, 0.01) # 100 equally spaced points

In [170]: xs, ys = np.meshgrid(points, points)

In [171]: ys

Out[171]:

array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],

[-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],

[-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],

...,

[ 4.97, 4.97, 4.97, ..., 4.97, 4.97, 4.97],

[ 4.98, 4.98, 4.98, ..., 4.98, 4.98, 4.98],

[ 4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]])

现在,评估函数就是编写与您编写的表达式相同的表达式,其中包含两点:

In [172]: z = np.sqrt(xs ** 2 + ys ** 2)

In [173]: z

Out[173]:

array([[7.0711, 7.064 , 7.0569, ..., 7.0499, 7.0569, 7.064 ],

[7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569],

[7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],

...,

[7.0499, 7.0428, 7.0357, ..., 7.0286, 7.0357, 7.0428],

[7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],

[7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569]])

使用 matplotlib 创建这个二维数组的可视化:

In [174]: import matplotlib.pyplot as plt

In [175]: plt.imshow(z, cmap=plt.cm.gray, extent=[-5, 5, -5, 5])

Out[175]:

In [176]: plt.colorbar()

Out[176]:

In [177]: plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")

Out[177]: Text(0.5, 1.0, 'Image plot of $\\sqrt{x^2 + y^2}$ for a grid of values'

)

使用 matplotlib 函数从函数值的二维数组创建图像图。c 如果您在 IPython 中工作,您可以通过执行以下命令关闭所有打开的绘图窗口:plt.close(“all”)

In [179]: plt.close("all")

将条件逻辑表示为数组运算

该函数是三元表达式的向量化版本。假设我们有一个布尔数组和两个值数组:numpy.wherex if condition else y

In [180]: xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])

In [181]: yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])

In [182]: cond = np.array([True, False, True, True, False])

假设我们想从 xarr 中获取一个值,只要在 cond 对应的值是 True 就执行,否则就从 yarr 中获取值

In [183]: result = [(x if c else y)

.....: for x, y, c in zip(xarr, yarr, cond)]

In [184]: result

Out[184]: [1.1, 2.2, 1.3, 1.4, 2.5]

这有多个问题。首先,对于大型数组,它不会很快(因为所有工作都是在解释的Python代码中完成的)。其次,它不适用于多维数组。对于多维数组,你可以通过一个函数调用来实现:numpy.where

In [185]: result = np.where(cond, xarr, yarr)

In [186]: result

Out[186]: array([1.1, 2.2, 1.3, 1.4, 2.5])

第二个和第三个参数不需要是数组;它们中的一个或两个可以是标量。数据分析中的典型用法是根据另一个数组生成一个新的值数组。假设你有一个随机生成的数据矩阵,你想用2替换所有正值,用-2替换所有负值。这可以通过使用:numpy.where来实现。

In [187]: arr = rng.standard_normal((4, 4))

In [188]: arr

Out[188]:

array([[ 2.6182, 0.7774, 0.8286, -0.959 ],

[-1.2094, -1.4123, 0.5415, 0.7519],

[-0.6588, -1.2287, 0.2576, 0.3129],

[-0.1308, 1.27 , -0.093 , -0.0662]])

In [189]: arr > 0

Out[189]:

array([[ True, True, True, False],

[False, False, True, True],

[False, False, True, True],

[False, True, False, False]])

In [190]: np.where(arr > 0, 2, -2)

Out[190]:

array([[ 2, 2, 2, -2],

[-2, -2, 2, 2],

[-2, -2, 2, 2],

[-2, 2, -2, -2]])

你可以同时使用标量和数组,例如:可以用常数 2 替换中的所有正值 numpy.where arr

In [191]: np.where(arr > 0, 2, arr) # set only positive values to 2

Out[191]:

array([[ 2. , 2. , 2. , -0.959 ],

[-1.2094, -1.4123, 2. , 2. ],

[-0.6588, -1.2287, 2. , 2. ],

[-0.1308, 2. , -0.093 , -0.0662]])

数学和统计方法

计算关于整个数组或沿轴的数据的统计信息的一组数学函数可以作为数组类的方法访问。您可以通过调用数组实例方法或使用顶级NumPy函数来使用聚合,如标准差、方差。当使用NumPy函数时,例如,必须传递要聚合的数组作为第一个参数。sum mean std numpy.sum

在这里,我生成一些正态分布的随机数据并计算一些聚合统计量:

In [192]: arr = rng.standard_normal((5, 4))

In [193]: arr

Out[193]:

array([[-1.1082, 0.136 , 1.3471, 0.0611],

[ 0.0709, 0.4337, 0.2775, 0.5303],

[ 0.5367, 0.6184, -0.795 , 0.3 ],

[-1.6027, 0.2668, -1.2616, -0.0713],

[ 0.474 , -0.4149, 0.0977, -1.6404]])

In [194]: arr.mean()

Out[194]: -0.08719744457434529

In [195]: np.mean(arr)

Out[195]: -0.08719744457434529

In [196]: arr.sum()

Out[196]: -1.743948891486906

函数 like and 采用一个可选参数,用于计算给定轴上的统计数据,从而生成一个维度的数组:mean sum axis

In [197]: arr.mean(axis=1)

Out[197]: array([ 0.109 , 0.3281, 0.165 , -0.6672, -0.3709])

In [198]: arr.sum(axis=0)

Out[198]: array([-1.6292, 1.0399, -0.3344, -0.8203])

这里,分别表示 “计算各行的平均值”、“计算各列的总和”。arr.mean(axis=1) arr.sum(axis=0)

其他方法类似,但不聚合,而是生成中间结果数组,如:cumsum cumprod

In [199]: arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])

In [200]: arr.cumsum()

Out[200]: array([ 0, 1, 3, 6, 10, 15, 21, 28])

在多维数组中,累积函数(如cumsum)返回一个与原数组相同大小的数组,但沿指定轴计算每个较低维度切片的部分累积值。

In [201]: arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

In [202]: arr

Out[202]:

array([[0, 1, 2],

[3, 4, 5],

[6, 7, 8]])

表达式arr.cumsum(axis=0) 计算沿着行的累积和,而 arr.cumsum(axis=1) 计算沿着列的和:

In [203]: arr.cumsum(axis=0)

Out[203]:

array([[ 0, 1, 2],

[ 3, 5, 7],

[ 9, 12, 15]])

In [204]: arr.cumsum(axis=1)

Out[204]:

array([[ 0, 1, 3],

[ 3, 7, 12],

[ 6, 13, 21]])

Basic array statistical methods

方法描述sum数组中或沿轴的所有元素的总和;零长度数组的总和为零mean算术平均值;对零长度数组无效(返回)NaNstd, var分别是标准差和方差min, max最小值和最大值argmin, argmax最小元素和最大元素的索引cumsum从 0 开始元素的累加值cumprod从 1 开始元素的累积值

布尔数组的方法

在上述方法中,布尔值被强制为 1 () 和 0 ()。因此,通常用作计算布尔数组中值的方法:True False sum True

In [205]: arr = rng.standard_normal(100)

In [206]: (arr > 0).sum() # Number of positive values

Out[206]: 48

In [207]: (arr <= 0).sum() # Number of non-positive values

Out[207]: 52

表达式中的括号对于能够调用的临时结果是必要的。(arr > 0).sum() sum() arr>0

测试数组中的一个或多个值是否为 True,同时检查每个值是否为 :True

In [208]: bools = np.array([False, False, True, False])

In [209]: bools.any()

Out[209]: True

In [210]: bools.all()

Out[210]: False

这些方法也适用于非布尔数组,其中非零元素被视为:True

排序

与 Python 的内置列表类型一样,可以使用 sort 方法对 NumPy 数组进行排序

In [211]: arr = rng.standard_normal(6)

In [212]: arr

Out[212]: array([ 0.0773, -0.6839, -0.7208, 1.1206, -0.0548, -0.0824])

In [213]: arr.sort()

In [214]: arr

Out[214]: array([-0.7208, -0.6839, -0.0824, -0.0548, 0.0773, 1.1206])

您可以通过将轴号传递给 sort 方法,来对多维数组中的每个一维部分进行原地排序。

In [215]: arr = rng.standard_normal((5, 3))

In [216]: arr

Out[216]:

array([[ 0.936 , 1.2385, 1.2728],

[ 0.4059, -0.0503, 0.2893],

[ 0.1793, 1.3975, 0.292 ],

[ 0.6384, -0.0279, 1.3711],

[-2.0528, 0.3805, 0.7554]])

arr.sort(axis=0) 对每一列内的值进行排序,而arr.sort(axis=1)对每一行的值进行排序

In [217]: arr.sort(axis=0)

In [218]: arr

Out[218]:

array([[-2.0528, -0.0503, 0.2893],

[ 0.1793, -0.0279, 0.292 ],

[ 0.4059, 0.3805, 0.7554],

[ 0.6384, 1.2385, 1.2728],

[ 0.936 , 1.3975, 1.3711]])

In [219]: arr.sort(axis=1)

In [220]: arr

Out[220]:

array([[-2.0528, -0.0503, 0.2893],

[-0.0279, 0.1793, 0.292 ],

[ 0.3805, 0.4059, 0.7554],

[ 0.6384, 1.2385, 1.2728],

[ 0.936 , 1.3711, 1.3975]])

像Python内置函数样的顶层方法,返回数组的排序副本,而不是就地修改数组。

In [221]: arr2 = np.array([5, -10, 7, 1, 0, -3])

In [222]: sorted_arr2 = np.sort(arr2)

In [223]: sorted_arr2

Out[223]: array([-10, -3, 0, 1, 5, 7])

唯一和其他集合逻辑

NumPy 对一维ndarray有一些基本的操作。一个常用的是,它返回数组中排序的唯一值:numpy.unique

In [224]: names = np.array(["Bob", "Will", "Joe", "Bob", "Will", "Joe", "Joe"])

In [225]: np.unique(names)

Out[225]: array(['Bob', 'Joe', 'Will'], dtype='

In [226]: ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])

In [227]: np.unique(ints)

Out[227]: array([1, 2, 3, 4])

numpy.unique 与纯Python相比

In [228]: sorted(set(names))

Out[228]: ['Bob', 'Joe', 'Will']

在许多情况下,NumPy版本更快,并且返回NumPy数组而不是Python列表。

另一个函数,测试一个数组中值在另一个数组中的隶属关系,返回一个布尔数组:numpy.in1d

In [229]: values = np.array([6, 0, 0, 3, 2, 5, 6])

In [230]: np.in1d(values, [2, 3, 6])

Out[230]: array([ True, False, False, True, True, False, True])

数组集操作

方法描述unique(x)计算已排序的唯一元素 xintersect1d(x, y)计算 和 中排序的公共元素 x yunion1d(x, y)计算元素的排序并集in1d(x, y)计算一个布尔数组,指示 的每个元素是否包含在 x ysetdiff1d(x, y)设置差异,元素中不在 x ysetxor1d(x, y)设置对称差分;元素在任一数组中,但不能同时在数组中

使用数组进行文件输入和输出

numpy.save 和 numpy.load 是在磁盘上有效地保存和加载数组数据的两个主要函数。默认情况下,数组以未压缩的原始二进制格式保存,文件扩展名为 .npy

In [231]: arr = np.arange(10)

In [232]: np.save("some_array", arr)

如果文件路径尚未以 .npy 结尾,则将附加扩展名。然后,磁盘上的数组可以加载:numpy.load

In [233]: np.load("some_array.npy")

Out[233]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

您可以使用数组作为关键字参数将数组保存在未压缩的存档中:numpy.savez

In [234]: np.savez("array_archive.npz", a=arr, b=arr)

加载 .npz 文件时,您会得到一个类似字典的对象,该对象会延迟加载各个数组:

In [235]: arch = np.load("array_archive.npz")

In [236]: arch["b"]

Out[236]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

如果您的数据压缩良好,您可能希望改用:numpy.savez_compressed

In [237]: np.savez_compressed("arrays_compressed.npz", a=arr, b=arr)

线性代数

线性代数运算,如矩阵乘法、分解、行列式和其他平方矩阵数学,是许多数组库的重要组成部分。将两个二维数组相乘是元素乘积,而矩阵乘法需要使用函数或中缀运算符。 既是数组方法,又是命名空间中用于执行矩阵乘法的函数:*dot @dot numpy

In [241]: x = np.array([[1., 2., 3.], [4., 5., 6.]])

In [242]: y = np.array([[6., 23.], [-1, 7], [8, 9]])

In [243]: x

Out[243]:

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

[4., 5., 6.]])

In [244]: y

Out[244]:

array([[ 6., 23.],

[-1., 7.],

[ 8., 9.]])

In [245]: x.dot(y)

Out[245]:

array([[ 28., 64.],

[ 67., 181.]])

x.dot(y)相当于:np.dot(x, y)

In [246]: np.dot(x, y)

Out[246]:

array([[ 28., 64.],

[ 67., 181.]])

二维数组和适当大小的一维数组之间的矩阵乘积产生一维数组:

In [247]: x @ np.ones(3)

Out[247]: array([ 6., 15.])

numpy.linalg 有一组标准的矩阵分解,以及逆分解和行列式之类的东西:

In [248]: from numpy.linalg import inv, qr

In [249]: X = rng.standard_normal((5, 5))

In [250]: mat = X.T @ X

In [251]: inv(mat)

Out[251]:

array([[ 3.4993, 2.8444, 3.5956, -16.5538, 4.4733],

[ 2.8444, 2.5667, 2.9002, -13.5774, 3.7678],

[ 3.5956, 2.9002, 4.4823, -18.3453, 4.7066],

[-16.5538, -13.5774, -18.3453, 84.0102, -22.0484],

[ 4.4733, 3.7678, 4.7066, -22.0484, 6.0525]])

In [252]: mat @ inv(mat)

Out[252]:

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

[ 0., 1., 0., 0., 0.],

[ 0., 0., 1., -0., 0.],

[ 0., 0., 0., 1., 0.],

[-0., 0., 0., 0., 1.]])

常用函数

方法描述diag将方阵的对角线(或非对角线)元素作为一维数组返回,或将一维数组转换为非对角线上为零的方阵dot矩阵乘法trace计算对角线元素的总和det计算矩阵行列式eig计算方阵的特征值和特征向量inv计算平方矩阵的倒数pinv计算矩阵的摩尔-彭罗斯伪逆函数qr计算二维码分解svd计算奇异值分解 (SVD)solve求解 x 的线性系统 Ax = b,其中 A 是方阵lstsq计算最小二乘解Ax = b

随机游走

随机游走也称随机漫步,下面是一个纯 Python 方法,使用内置模块实现 1,000 步的单个随机游走

#! blockstart

import random

position = 0

walk = [position]

nsteps = 1000

for _ in range(nsteps):

step = 1 if random.randint(0, 1) else -1

position += step

walk.append(position)

#! blockend

In [255]: plt.plot(walk[:100])

您可以进行观察,该观察值是随机步骤的累积总和,并且可以计算为数组表达式。因此,我使用该模块一次抽取 1,000 次抛硬币,将它们设置为 1 和 –1,并计算累积总和:walk numpy.random

In [256]: nsteps = 1000

In [257]: rng = np.random.default_rng(seed=12345) # fresh random generator

In [258]: draws = rng.integers(0, 2, size=nsteps)

In [259]: steps = np.where(draws == 0, 1, -1)

In [260]: walk = steps.cumsum()

由此,我们可以开始提取统计数据,例如步行轨迹上的最小值和最大值:

In [261]: walk.min()

Out[261]: -8

In [262]: walk.max()

Out[262]: 50

In [263]: (np.abs(walk) >= 10).argmax()

Out[263]: 155

在NumPy高级应用中,将深入探讨 NumPy 的功能,以帮助您进一步发展您的阵列计算技能。

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: