N维数组 (ndarray)#

一个 ndarray 是一个(通常是固定大小的)多维容器,包含相同类型和大小的项目.数组的维数和项目数由其 形状 定义,这是一个由 N 个非负整数组成的 元组 ,指定每个维度的大小.数组中项目类型由一个单独的 数据类型对象 (dtype) 指定,每个 ndarray 都关联一个这样的对象.

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

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

示例

一个大小为 2 x 3 的二维数组,由 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 非常灵活,:class:ndarray 对象可以适应任何 跨步索引方案.在跨步方案中,N 维索引 \((n_0, n_1, ..., n_{N-1})\) 对应于偏移量(以字节为单位):

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

从与数组关联的内存块的开头开始.这里,:math:s_k 是整数,用于指定数组的 步幅 .:term:列优先 顺序(例如,在 Fortran 语言和 Matlab 中使用)和 行优先 顺序(在 C 语言中使用)方案只是特定类型的步幅方案,并且对应于可以通过步幅 寻址 的内存:

\[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 风格的连续数组可以使用上述步幅进行寻址,但实际步幅可能不同.这可能发生在两种情况下:

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

  2. 如果一个数组没有元素(self.size == 0),则没有合法的索引,并且步长永远不会被使用.任何没有元素的数组都可以被认为是 C 风格和 Fortran 风格连续的.

第一点意味着 selfself.squeeze() 总是具有相同的连续性和 aligned 标志值.这也意味着即使是一个高维数组,也可能同时是 C 风格和 Fortran 风格连续的.

如果所有元素和基偏移量的内存偏移量是 self.itemsize 的倍数,则认为数组是对齐的.理解 内存对齐 会在大多数硬件上带来更好的性能.

警告

通常 成立的是,对于C风格的连续数组 self.strides[-1] == self.itemsize 或者对于Fortran风格的连续数组 self.strides[0] == self.itemsize 是正确的.

ndarrays 中的数据在 行优先 (C) 顺序中,除非另有说明,但例如,:ref:基本数组切片 通常会产生不同方案的 视图.

备注

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

一个在数组上进行一维迭代的迭代器.

数组接口#

参见

数组.接口.

__array_interface__

数组接口的Python端

__array_struct__

数组接口的C端

ctypes 外部函数接口#

ndarray.ctypes

一个对象,用于简化数组与 ctypes 模块的交互.

数组方法#

一个 ndarray 对象有许多方法,这些方法以某种方式操作或与数组一起操作,通常返回一个数组结果.这些方法简要解释如下.(每个方法的文档字符串有更完整的描述.)

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

数组转换#

ndarray.item(*args)

将数组的元素复制到标准的 Python 标量并返回它.

ndarray.tolist()

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

ndarray.tostring([order])

tobytes 的兼容别名,具有完全相同的行为.

ndarray.tobytes([order])

构建包含数组中原始数据字节的Python字节.

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)

用一个标量值填充数组.

形状操作#

对于重塑、调整大小和转置,单个元组参数可以用 n 个整数代替,这些整数将被解释为一个 n 元组.

ndarray.reshape(shape, /, *[, order, copy])

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

ndarray.resize(new_shape[, refcheck])

就地改变数组的形状和大小.

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])

对于所有 n 在索引中,设置 a.flat[n] = values[n].

ndarray.repeat(repeats[, axis])

重复数组的元素.

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

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

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

就地排序数组.

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

返回可以对此数组进行排序的索引.

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

部分排序数组中的元素,使得第 k 个位置的元素在其在排序数组中应有的位置.

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 是一个整数,那么操作是在给定的轴上进行的(对于沿着给定轴可以创建的每个1-D子数组).

toctree 是一个 reStructuredText 指令 ,这是一个非常多功能的标记.指令可以有参数、选项和内容.

一个大小为 3 x 3 x 3 的三维数组,在其三个轴上求和:

>>> 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, /)

返回自身值.

ndarray.__mul__(value, /)

返回 self*value.

ndarray.__truediv__(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 += 3j`` 与 a = 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__()

用于序列化.

ndarray.__setstate__(state, /)

用于解封.

基本定制:

ndarray.__new__(*args, **kwargs)

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

对于 dtype 参数,如果未提供 dtype 或其与数组的数据类型匹配,则返回对自身的新的引用.

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

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

容器定制化:(见 索引

ndarray.__len__(/)

返回 len(self).

ndarray.__getitem__(key, /)

返回 self[key].

ndarray.__setitem__(key, value, /)

将 self[key] 设置为 value.

ndarray.__contains__(key, /)

返回键在 self 中

转换;操作 int()float()complex().它们仅适用于包含一个元素的数组,并返回适当的标量.

字符串表示:

ndarray.__str__(/)

返回 str(self).

ndarray.__repr__(/)

返回 repr(self).

用于输入的实用方法:

ndarray.__class_getitem__(item, /)

返回一个围绕 ndarray 类型的参数化包装器.