N维数组 (ndarray)#

一个 ndarray 是一个(通常是固定大小的)多维容器,包含相同类型和大小的元素。数组的维度数量和元素数量由其 shape 定义,它是一个由 N 个非负整数组成的 tuple,指定每个维度的尺寸。数组中元素的类型由一个单独的 数据类型对象 (dtype) 指定,每个 ndarray 都关联有一个 dtype。

与 Python 中的其他容器对象一样,ndarray 的内容可以通过 索引或切片(例如,使用 N 个整数)以及通过 ndarray 的方法和属性来访问和修改。

不同的 ndarrays 可以共享相同的数据,因此在一个 ndarray 中所做的更改可能在另一个 ndarray 中可见。也就是说,一个 ndarray 可以是另一个 ndarray 的 “视图”,它所引用的数据由 “基” ndarray 管理。ndarray 也可以是 Python 字符串 或实现了 memoryview数组 接口的对象拥有的内存的视图。

示例

一个 2x3 大小的二维数组,由 4 字节整数元素组成

>>> import numpy as np
>>> x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
>>> type(x)
<class 'numpy.ndarray'>
>>> x.shape
(2, 3)
>>> x.dtype
dtype('int32')

可以使用类似 Python 容器的语法来索引数组

>>> # The element of x in the *second* row, *third* column, namely, 6.
>>> x[1, 2]
   6

例如,切片可以生成数组的视图

>>> y = x[:,1]
>>> y
array([2, 5], dtype=int32)
>>> y[0] = 9 # this also changes the corresponding element in x
>>> y
array([9, 5], dtype=int32)
>>> x
array([[1, 9, 3],
       [4, 5, 6]], dtype=int32)

构造数组#

可以使用 数组创建例程 中详述的例程来构造新数组,也可以使用低级的 ndarray 构造函数

ndarray(shape[, dtype, buffer, offset, ...])

数组对象表示一个多维、同质的、固定大小元素的数组。

索引数组#

数组可以使用扩展的 Python 切片语法 array[selection] 来索引。类似的语法也用于访问 结构化数据类型 中的字段。

另请参阅

数组索引.

ndarray 的内部内存布局#

ndarray 类的一个实例由一个连续的一维计算机内存段(由数组或某个其他对象拥有)组成,并结合一个将 N 个整数映射到内存块中元素位置的索引方案。索引可以变化的范围由数组的 shape 指定。每个元素占用多少字节以及字节如何解释由与数组关联的 数据类型对象 定义。

内存段本质上是一维的,并且存在许多不同的方案来在一维块中排列 N 维数组的元素。NumPy 非常灵活,ndarray 对象可以适应任何 跨步索引方案。在跨步方案中,N 维索引 \((n_0, n_1, ..., n_{N-1})\) 对应于与数组关联的内存块开始处的偏移量(以字节为单位)

\[n_{\mathrm{offset}} = \sum_{k=0}^{N-1} s_k n_k\]

。其中 \(s_k\) 是指定数组 strides 的整数。 列主序(例如,在 Fortran 语言和 Matlab 中使用)和 行主序(在 C 中使用)方案只是跨步方案的特定类型,对应于可以由 strides 寻址 的内存

\[s_k^{\mathrm{column}} = \mathrm{itemsize} \prod_{j=0}^{k-1} d_j , \quad s_k^{\mathrm{row}} = \mathrm{itemsize} \prod_{j=k+1}^{N-1} d_j .\]

其中 \(d_j\) = self.shape[j]

C 和 Fortran 顺序都是 连续的,即单段内存布局,其中内存块的每个部分都可以通过索引的某种组合来访问。

注意

连续数组单段数组是同义词,并在整个文档中互换使用。

虽然具有相应标志的 C 样式和 Fortran 样式连续数组可以使用上述 strides 来寻址,但实际的 strides 可能不同。这种情况可能发生在两种情况下:

  1. 如果 self.shape[k] == 1,那么对于任何合法的索引 index[k] == 0。这意味着在偏移量公式中 \(n_k = 0\),因此 \(s_k\) = self.strides[k] 的值是任意的。

  2. 如果数组没有元素(self.size == 0),则没有合法索引,并且 strides 从未使用过。任何没有元素的数组都可以被认为是 C 样式和 Fortran 样式的连续。

第一点意味着 selfself.squeeze() 始终具有相同的 contiguity 和 aligned 标志值。这也意味着即使是高维数组也可以同时是 C 样式和 Fortran 样式的连续。

如果内存偏移量和基地址偏移量都是 self.itemsize 的倍数,则该数组被认为是已对齐的。理解内存对齐可以在大多数硬件上获得更好的性能。

警告

对于 C 样式的连续数组,self.strides[-1] == self.itemsize 通常不成立;对于 Fortran 样式的连续数组,self.strides[0] == self.itemsize 通常也不成立。

ndarrays 中的数据默认为 行主序(C 顺序),除非另有说明,但是,例如,基本数组切片 通常会生成不同方案的 视图

注意

NumPy 中的一些算法适用于任意跨步的数组。然而,有些算法需要单段数组。当将一个跨步不规则的数组传递给这类算法时,会自动创建一个副本。

数组属性#

数组属性反映了数组本身固有的信息。通常,通过数组的属性访问允许您在不创建新数组的情况下获取(有时也可以设置)数组的固有属性。公开的属性是数组的核心部分,只有其中一些属性在不创建新数组的情况下可以有意义地重置。下面是每个属性的信息。

内存布局#

以下属性包含有关数组内存布局的信息

ndarray.flags

有关数组内存布局的信息。

ndarray.shape

数组的维度元组。

ndarray.strides

遍历数组时,每个维度需要跳过的字节数。

ndarray.ndim

数组的维度数。

ndarray.data

指向数组数据开始处的 Python 缓冲区对象。

ndarray.size

数组中的元素数量。

ndarray.itemsize

数组一个元素占用的字节数。

ndarray.nbytes

数组元素消耗的总字节数。

ndarray.base

如果内存来自其他对象,则为基对象。

数据类型#

另请参阅

数据类型对象

与数组相关的数据类型对象可以在 dtype 属性中找到

ndarray.dtype

数组元素的数据类型。

其他属性#

ndarray.T

转置数组的视图。

ndarray.real

数组的实部。

ndarray.imag

数组的虚部。

ndarray.flat

数组的 1-D 迭代器。

数组接口#

另请参阅

数组接口协议.

__array_interface__

数组接口的 Python 端

__array_struct__

数组接口的 C 端

ctypes 外部函数接口#

ndarray.ctypes

一个简化数组与 ctypes 模块交互的对象。

数组方法#

ndarray 对象有许多方法,它们以某种方式对数组进行操作或与数组配合,通常返回数组结果。这些方法将在下面简要介绍。(每个方法的文档字符串都有更完整的描述。)

对于以下方法,numpy 中也有相应的函数:allanyargmaxargminargpartitionargsortchooseclipcompresscopycumprodcumsumdiagonalimagmaxmeanminnonzeropartitionprodputravelrealrepeatreshaperoundsearchsortedsortsqueezestdsumswapaxestaketracetransposevar

数组转换#

ndarray.item(*args)

将数组的单个元素复制到标准的 Python 标量并返回。

ndarray.tolist()

将数组作为深度为 a.ndim 的嵌套 Python 标量列表返回。

ndarray.tobytes([order])

构建包含数组原始数据字节的 Python bytes 对象。

ndarray.tofile(fid, /[, sep, format])

将数组以文本或二进制(默认)形式写入文件。

ndarray.dump(file)

将数组的 pickle 转储到指定文件。

ndarray.dumps()

将数组的 pickle 以字符串形式返回。

ndarray.astype(dtype[, order, casting, ...])

将数组复制并转换为指定类型。

ndarray.byteswap([inplace])

交换数组元素的字节

ndarray.copy([order])

返回数组的副本。

ndarray.view([dtype][, type])

具有相同数据的数组的新视图。

ndarray.getfield(dtype[, offset])

以给定类型返回数组的一个字段。

ndarray.setflags([write, align, uic])

分别设置数组标志 WRITEABLE、ALIGNED、WRITEBACKIFCOPY。

ndarray.fill(value)

用标量值填充数组。

形状操作#

对于 reshape、resize 和 transpose,单个数组参数可以被 n 个整数替换,这些整数将被解释为 n 元组。

ndarray.reshape(a.reshape)

返回一个具有新形状的包含相同数据的数组。

ndarray.resize(a.resize)

原地更改数组的形状和大小。

ndarray.transpose(*axes)

返回一个视图,其中数组的轴已转置。

ndarray.swapaxes(axis1, axis2, /)

返回数组的视图,其中 axis1axis2 已交换。

ndarray.flatten([order])

返回数组的副本,展平成一维。

ndarray.ravel([order])

返回一个展平的数组。

ndarray.squeeze([axis])

a 中移除长度为一的轴。

条目选择与操作#

对于采用 axis 关键字的数组方法,它默认为 None。如果 axis 为 None,则数组被视为一维数组。axis 的任何其他值表示操作应沿哪个维度进行。

ndarray.take(indices[, axis, out, mode])

a 中按给定索引返回一个由元素组成的数组。

ndarray.put(indices, values[, mode])

对于所有 indices 中的 n,设置 a.flat[n] = values[n]

ndarray.repeat(repeats[, axis])

重复数组中的元素。

ndarray.choose(choices[, out, mode])

使用索引数组从一组选项中构造一个新数组。

ndarray.sort([axis, kind, order, stable])

就地排序数组。

ndarray.argsort([axis, kind, order, stable])

返回将此数组排序的索引。

ndarray.partition(kth[, axis, kind, order])

部分排序数组中的元素,使 k-th 位置的元素处于它在已排序数组中的位置。

ndarray.argpartition(kth[, axis, kind, order])

返回将此数组分区将产生的索引。

ndarray.searchsorted(v[, side, sorter])

查找元素 v 应该插入到 a 中的索引,以保持顺序。

ndarray.nonzero()

返回非零元素的索引。

ndarray.compress(condition[, axis, out])

沿给定轴返回此数组的选定切片。

ndarray.diagonal([offset, axis1, axis2])

返回指定的对角线。

计算#

其中许多方法接受一个名为 axis 的参数。在这种情况下,

  • 如果 axisNone(默认值),则数组被视为一维数组,操作将在整个数组上执行。如果 self 是一个 0 维数组或数组标量,此行为也是默认行为。(数组标量是类型/类 float32、float64 等的实例,而 0 维数组是精确包含一个数组标量的 ndarray 实例。)

  • 如果 axis 是一个整数,则操作将沿给定轴进行(对于沿给定轴可以创建的每个一维子数组)。

axis 参数的示例

一个 3x3x3 大小的三维数组,在它的三个轴上分别求和

>>> import numpy as np
>>> x = np.arange(27).reshape((3,3,3))
>>> x
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]]])
>>> x.sum(axis=0)
array([[27, 30, 33],
      [36, 39, 42],
      [45, 48, 51]])
>>> # for sum, axis is the first keyword, so we may omit it,
>>> # specifying only its value
>>> x.sum(0), x.sum(1), x.sum(2)
(array([[27, 30, 33],
      [36, 39, 42],
      [45, 48, 51]]),
array([[ 9, 12, 15],
      [36, 39, 42],
      [63, 66, 69]]),
array([[ 3, 12, 21],
      [30, 39, 48],
      [57, 66, 75]]))

dtype 参数指定了约简操作(如求和)应该在哪个数据类型上进行。默认的约简数据类型与 self 的数据类型相同。为避免溢出,使用更大的数据类型执行约简可能很有用。

对于几种方法,还可以提供一个可选的 out 参数,结果将放入给定的输出数组中。out 参数必须是一个 ndarray 并且具有相同数量的元素。它可以具有不同的数据类型,在这种情况下将执行类型转换。

ndarray.max([axis, out, keepdims, initial, ...])

沿给定轴返回最大值。

ndarray.argmax([axis, out, keepdims])

返回沿给定轴的最大值的索引。

ndarray.min([axis, out, keepdims, initial, ...])

沿给定轴返回最小值。

ndarray.argmin([axis, out, keepdims])

返回沿给定轴的最小值索引。

ndarray.clip([min, max, out])

返回一个值被限制在 [min, max] 范围内的数组。

ndarray.conj()

计算所有元素的复共轭。

ndarray.round([decimals, out])

返回 a,其中每个元素都四舍五入到指定的小数位数。

ndarray.trace([offset, axis1, axis2, dtype, out])

返回数组对角线上的元素之和。

ndarray.sum([axis, dtype, out, keepdims, ...])

沿给定轴返回数组元素的总和。

ndarray.cumsum([axis, dtype, out])

返回沿给定轴的元素的累积和。

ndarray.mean([axis, dtype, out, keepdims, where])

返回给定轴上数组元素的平均值。

ndarray.var([axis, dtype, out, ddof, ...])

返回数组元素在给定轴上的方差。

ndarray.std([axis, dtype, out, ddof, ...])

返回给定轴上数组元素的标准差。

ndarray.prod([axis, dtype, out, keepdims, ...])

返回数组元素在给定轴上的乘积

ndarray.cumprod([axis, dtype, out])

返回沿给定轴的元素的累积乘积。

ndarray.all([axis, out, keepdims, where])

如果所有元素都求值为 True,则返回 True。

ndarray.any([axis, out, keepdims, where])

如果 a 的任何元素评估为 True,则返回 True。

算术、矩阵乘法和比较运算#

ndarrays 上的算术和比较运算被定义为逐元素运算,并且通常产生 ndarray 对象作为结果。

每个算术运算(+, -, *, /, //, %, divmod(), **pow(), <<, >>, &, ^, |, ~)和比较运算(==, <, >, <=, >=, !=)等同于 NumPy 中相应的通用函数(或简称为 ufunc)。有关更多信息,请参阅 通用函数 部分。

比较运算符

ndarray.__lt__(value, /)

返回 self<value。

ndarray.__le__(value, /)

返回 self<=value。

ndarray.__gt__(value, /)

返回 self>value。

ndarray.__ge__(value, /)

返回 self>=value。

ndarray.__eq__(value, /)

返回 self==value。

ndarray.__ne__(value, /)

返回 self!=value。

数组的真值(bool()

ndarray.__bool__(/)

如果 self 为真则返回 True,否则返回 False。

注意

对数组的真值测试会调用 ndarray.__bool__,如果数组中的元素数量不是 1,则会引发错误,因为这种数组的真值是模棱两可的。在这种情况下,请使用 .any().all() 来明确意图。(如果您想检查数组是否为空,请使用例如 .size > 0。)

一元运算

算术

ndarray.__add__(value, /)

返回 self+value。

ndarray.__sub__(value, /)

返回 self-value。

ndarray.__mul__(value, /)

返回 self*value。

ndarray.__truediv__(value, /)

返回 self/value。

ndarray.__floordiv__(value, /)

返回 self//value。

ndarray.__mod__(value, /)

返回 self%value。

ndarray.__divmod__(value, /)

返回 divmod(self, value)。

ndarray.__pow__(value[, mod])

返回 pow(self, value, mod)。

ndarray.__lshift__(value, /)

返回 self<<value。

ndarray.__rshift__(value, /)

返回 self>>value。

ndarray.__and__(value, /)

返回 self&value。

ndarray.__or__(value, /)

返回 self|value。

ndarray.__xor__(value, /)

返回 self^value。

注意

  • 传递给 pow 的任何第三个参数都会被静默忽略,因为底层的 ufunc 只接受两个参数。

  • 由于 ndarray 是一个内置类型(用 C 编写),所以 __r{op}__ 特殊方法没有直接定义。

  • 用于实现数组许多算术特殊方法的函数可以通过 __array_ufunc__ 进行修改。

算术,原地操作

ndarray.__iadd__(value, /)

返回 self+=value。

ndarray.__isub__(value, /)

返回 self-=value。

ndarray.__imul__(value, /)

返回 self*=value。

ndarray.__itruediv__(value, /)

返回 self/=value。

ndarray.__ifloordiv__(value, /)

返回 self//=value。

ndarray.__imod__(value, /)

返回 self%=value。

ndarray.__ipow__(value, /)

返回 self**=value。

ndarray.__ilshift__(value, /)

返回 self<<=value。

ndarray.__irshift__(value, /)

返回 self>>=value。

ndarray.__iand__(value, /)

返回 self&=value。

ndarray.__ior__(value, /)

返回 self|=value。

ndarray.__ixor__(value, /)

返回 self^=value。

警告

就地操作会使用由两个操作数的类型决定的精度执行计算,但会静默地将结果(如果需要)向下转换,使其能够重新放入数组。因此,对于混合精度计算,A {op}= B 可能与 A = A {op} B 不同。例如,假设 a = ones((3,3))。那么,a += 3ja = a + 3j 不同:虽然它们都执行相同的计算,但 a += 3 将结果转换为适合放回 a,而 a = a + 3j 则将名称 a 重新绑定到结果。

矩阵乘法

ndarray.__matmul__(value, /)

返回 self@value

注意

矩阵运算符 @@= 是在 Python 3.5 中根据 PEP 465 引入的,而 @ 运算符是在 NumPy 1.10.0 中引入的。更多信息可以在 matmul 文档中找到。

特殊方法#

对于标准库函数

ndarray.__copy__()

如果对数组调用 copy.copy,则使用此方法。

ndarray.__deepcopy__(memo, /)

如果对数组调用 copy.deepcopy,则使用此方法。

ndarray.__reduce__()

用于 pickle。

ndarray.__setstate__(state, /)

用于 unpickle。

基本自定义

ndarray.__new__(*args, **kwargs)

ndarray.__array__([dtype], *[, copy])

对于 dtype 参数,如果未给出 dtype 或其与数组的数据类型匹配,则返回 self 的新引用。

ndarray.__array_wrap__(array[, context[, ...)

返回一个与 self 类型相同的 array 的视图。

容器自定义:(参见 索引

ndarray.__len__(/)

返回 len(self)。

ndarray.__getitem__(key, /)

返回 self[key]。

ndarray.__setitem__(key, value, /)

将 self[key] 设置为 value。

ndarray.__contains__(key, /)

返回 key in self。

转换;int()float()complex() 操作。它们仅对包含一个元素的数组有效,并返回相应的标量。

字符串表示

ndarray.__str__(/)

返回 str(self)。

ndarray.__repr__(/)

返回 repr(self)。

用于类型的实用方法

ndarray.__class_getitem__($cls, item, /)

ndarray[shape, dtype]