NumPy 1.26 中文官方指南(一)(2)https://developer.aliyun.com/article/1510632
一个例子
>>> import numpy as np >>> a = np.arange(15).reshape(3, 5) >>> a array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]) >>> a.shape (3, 5) >>> a.ndim 2 >>> a.dtype.name 'int64' >>> a.itemsize 8 >>> a.size 15 >>> type(a) <class 'numpy.ndarray'> >>> b = np.array([6, 7, 8]) >>> b array([6, 7, 8]) >>> type(b) <class 'numpy.ndarray'>
数组创建
有几种创建数组的方法。
例如,您可以使用array
函数从常规 Python 列表或元组创建数组。结果数组的类型是从序列中元素的类型推断出来的。
>>> import numpy as np >>> a = np.array([2, 3, 4]) >>> a array([2, 3, 4]) >>> a.dtype dtype('int64') >>> b = np.array([1.2, 3.5, 5.1]) >>> b.dtype dtype('float64')
一个常见错误是使用多个参数调用array
,而不是提供一个序列作为参数。
>>> a = np.array(1, 2, 3, 4) # WRONG Traceback (most recent call last): ... TypeError: array() takes from 1 to 2 positional arguments but 4 were given >>> a = np.array([1, 2, 3, 4]) # RIGHT
array
将序列转换为二维数组,序列的序列转换为三维数组,依此类推。
>>> b = np.array([(1.5, 2, 3), (4, 5, 6)]) >>> b array([[1.5, 2\. , 3\. ], [4\. , 5\. , 6\. ]])
数组的类型也可以在创建时显式指定:
>>> c = np.array([[1, 2], [3, 4]], dtype=complex) >>> c array([[1.+0.j, 2.+0.j], [3.+0.j, 4.+0.j]])
通常,数组的元素最初是未知的,但其大小是已知的。因此,NumPy 提供了几个函数来创建具有初始占位内容的数组。这减少了增长数组的必要性,这是一个昂贵的操作。
函数zeros
创建一个全零数组,函数ones
创建一个全一数组,函数empty
创建一个其初始内容是随机的并且取决于内存状态的数组。默认情况下,创建的数组的 dtype 是float64
,但可以通过关键字参数dtype
进行指定。
>>> np.zeros((3, 4)) array([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]) >>> np.ones((2, 3, 4), dtype=np.int16) array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]], dtype=int16) >>> np.empty((2, 3)) array([[3.73603959e-262, 6.02658058e-154, 6.55490914e-260], # may vary [5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])
为了创建数字序列,NumPy 提供了类似于 Python 内置的range
的arange
函数,但它返回一个数组。
>>> np.arange(10, 30, 5) array([10, 15, 20, 25]) >>> np.arange(0, 2, 0.3) # it accepts float arguments array([0\. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
当arange
与浮点数参数一起使用时,通常无法预测获得的元素数量,这是由于有限浮点精度。因此,通常最好使用接收我们想要的元素数量作为参数而不是步长的函数linspace
:
>>> from numpy import pi >>> np.linspace(0, 2, 9) # 9 numbers from 0 to 2 array([0\. , 0.25, 0.5 , 0.75, 1\. , 1.25, 1.5 , 1.75, 2\. ]) >>> x = np.linspace(0, 2 * pi, 100) # useful to evaluate function at lots of points >>> f = np.sin(x)
另请参阅
array
, zeros
, zeros_like
, ones
, ones_like
, empty
, empty_like
, arange
, linspace
, numpy.random.Generator.rand, numpy.random.Generator.randn, fromfunction
, fromfile
打印数组
当打印数组时,NumPy 以类似嵌套列表的方式显示它,但布局如下:
- 最后一个轴从左到右打印,
- 倒数第二个从上到下打印,
- 剩余部分也从上到下打印,每个切片与下一个切片之间由一个空行分隔。
一维数组被打印为行,二维数组被打印为矩阵,三维数组被打印为矩阵的列表。
>>> a = np.arange(6) # 1d array >>> print(a) [0 1 2 3 4 5] >>> >>> b = np.arange(12).reshape(4, 3) # 2d array >>> print(b) [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]] >>> >>> c = np.arange(24).reshape(2, 3, 4) # 3d array >>> print(c) [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]]
请参见下面以获取有关reshape
的更多详细信息。
如果数组太大而无法打印,NumPy 会自动跳过数组的中间部分,仅打印角落:
>>> print(np.arange(10000)) [ 0 1 2 ... 9997 9998 9999] >>> >>> print(np.arange(10000).reshape(100, 100)) [[ 0 1 2 ... 97 98 99] [ 100 101 102 ... 197 198 199] [ 200 201 202 ... 297 298 299] ... [9700 9701 9702 ... 9797 9798 9799] [9800 9801 9802 ... 9897 9898 9899] [9900 9901 9902 ... 9997 9998 9999]]
要禁用此行为并强制 NumPy 打印整个数组,可以使用set_printoptions
更改打印选项。
>>> np.set_printoptions(threshold=sys.maxsize) # sys module should be imported
基本操作
数组上的算术运算逐元素应用。创建一个新数组并用结果填充。
>>> a = np.array([20, 30, 40, 50]) >>> b = np.arange(4) >>> b array([0, 1, 2, 3]) >>> c = a - b >>> c array([20, 29, 38, 47]) >>> b**2 array([0, 1, 4, 9]) >>> 10 * np.sin(a) array([ 9.12945251, -9.88031624, 7.4511316 , -2.62374854]) >>> a < 35 array([ True, True, False, False])
与许多矩阵语言不同,在 NumPy 数组中,乘积运算符*
是按元素操作的。可以使用@
运算符(在 python >=3.5 中)或dot
函数或方法执行矩阵乘积:
>>> A = np.array([[1, 1], ... [0, 1]]) >>> B = np.array([[2, 0], ... [3, 4]]) >>> A * B # elementwise product array([[2, 0], [0, 4]]) >>> A @ B # matrix product array([[5, 4], [3, 4]]) >>> A.dot(B) # another matrix product array([[5, 4], [3, 4]])
一些操作,比如+=
和*=
,是就地修改现有数组而不是创建新数组。
>>> rg = np.random.default_rng(1) # create instance of default random number generator >>> a = np.ones((2, 3), dtype=int) >>> b = rg.random((2, 3)) >>> a *= 3 >>> a array([[3, 3, 3], [3, 3, 3]]) >>> b += a >>> b array([[3.51182162, 3.9504637 , 3.14415961], [3.94864945, 3.31183145, 3.42332645]]) >>> a += b # b is not automatically converted to integer type Traceback (most recent call last): ... numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
在操作不同类型的数组时,结果数组的类型对应于更一般或更精确的类型(这种行为称为向上转型)。
>>> a = np.ones(3, dtype=np.int32) >>> b = np.linspace(0, pi, 3) >>> b.dtype.name 'float64' >>> c = a + b >>> c array([1\. , 2.57079633, 4.14159265]) >>> c.dtype.name 'float64' >>> d = np.exp(c * 1j) >>> d array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j, -0.54030231-0.84147098j]) >>> d.dtype.name 'complex128'
许多一元操作,比如计算数组中所有元素的和,都作为ndarray
类的方法实现。
>>> a = rg.random((2, 3)) >>> a array([[0.82770259, 0.40919914, 0.54959369], [0.02755911, 0.75351311, 0.53814331]]) >>> a.sum() 3.1057109529998157 >>> a.min() 0.027559113243068367 >>> a.max() 0.8277025938204418
默认情况下,这些操作会将数组视为数字列表进行,而不考虑其形状。但是,通过指定axis
参数,您可以沿着数组的指定轴应用操作:
>>> b = np.arange(12).reshape(3, 4) >>> b array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> >>> b.sum(axis=0) # sum of each column array([12, 15, 18, 21]) >>> >>> b.min(axis=1) # min of each row array([0, 4, 8]) >>> >>> b.cumsum(axis=1) # cumulative sum along each row array([[ 0, 1, 3, 6], [ 4, 9, 15, 22], [ 8, 17, 27, 38]])
通用函数
NumPy 提供了一些熟悉的数学函数,如 sin、cos 和 exp。在 NumPy 中,这些被称为“通用函数”(ufunc
)。在 NumPy 中,这些函数对数组进行逐元素操作,并产生一个数组作为输出。
>>> B = np.arange(3) >>> B array([0, 1, 2]) >>> np.exp(B) array([1\. , 2.71828183, 7.3890561 ]) >>> np.sqrt(B) array([0\. , 1\. , 1.41421356]) >>> C = np.array([2., -1., 4.]) >>> np.add(B, C) array([2., 0., 6.])
另见
all
, any
, apply_along_axis
, argmax
, argmin
, argsort
, average
, bincount
, ceil
, clip
, conj
, corrcoef
, cov
, cross
, cumprod
, cumsum
, diff
, dot
, floor
, inner
, invert
, lexsort
, max
, maximum
, mean
, median
, min
, minimum
, nonzero
, outer
, prod
, re
, round
, sort
, std
, sum
, trace
, transpose
, var
, vdot
, vectorize
, where
索引、切片和迭代
一维数组可以像列表和其他 Python 序列一样进行索引、切片和迭代。
>>> a = np.arange(10)**3 >>> a array([ 0, 1, 8, 27, 64, 125, 216, 343, 512, 729]) >>> a[2] 8 >>> a[2:5] array([ 8, 27, 64]) >>> # equivalent to a[0:6:2] = 1000; >>> # from start to position 6, exclusive, set every 2nd element to 1000 >>> a[:6:2] = 1000 >>> a array([1000, 1, 1000, 27, 1000, 125, 216, 343, 512, 729]) >>> a[::-1] # reversed a array([ 729, 512, 343, 216, 125, 1000, 27, 1000, 1, 1000]) >>> for i in a: ... print(i**(1 / 3.)) ... 9.999999999999998 # may vary 1.0 9.999999999999998 3.0 9.999999999999998 4.999999999999999 5.999999999999999 6.999999999999999 7.999999999999999 8.999999999999998
多维数组可以有每个轴的一个索引。这些索引用逗号分隔的元组给出:
>>> def f(x, y): ... return 10 * x + y ... >>> b = np.fromfunction(f, (5, 4), dtype=int) >>> b array([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23], [30, 31, 32, 33], [40, 41, 42, 43]]) >>> b[2, 3] 23 >>> b[0:5, 1] # each row in the second column of b array([ 1, 11, 21, 31, 41]) >>> b[:, 1] # equivalent to the previous example array([ 1, 11, 21, 31, 41]) >>> b[1:3, :] # each column in the second and third row of b array([[10, 11, 12, 13], [20, 21, 22, 23]])
当提供的索引少于轴的数量时,缺少的索引被视为完整切片:
>>> b[-1] # the last row. Equivalent to b[-1, :] array([40, 41, 42, 43])
表达式b[i]
中的括号内被视为i
后面跟着尽可能多的:
来表示剩下的轴。NumPy 还允许您使用点号表示为b[i, ...]
。
省略号(...
)表示为产生一个完整索引元组所需的冒号。例如,如果x
是一个具有 5 个轴的数组,则
x[1, 2, ...]
等同于x[1, 2, :, :, :]
,x[..., 3]
到x[:, :, :, :, 3]
和x[4, ..., 5, :]
到x[4, :, :, 5, :]
。
>>> c = np.array([[[ 0, 1, 2], # a 3D array (two stacked 2D arrays) ... [ 10, 12, 13]], ... [[100, 101, 102], ... [110, 112, 113]]]) >>> c.shape (2, 2, 3) >>> c[1, ...] # same as c[1, :, :] or c[1] array([[100, 101, 102], [110, 112, 113]]) >>> c[..., 2] # same as c[:, :, 2] array([[ 2, 13], [102, 113]])
对多维数组的迭代是针对第一个轴进行的:
>>> for row in b: ... print(row) ... [0 1 2 3] [10 11 12 13] [20 21 22 23] [30 31 32 33] [40 41 42 43]
但是,如果想要对数组中的每个元素执行操作,可以使用flat
属性,它是一个对数组的所有元素进行迭代的迭代器:
>>> for element in b.flat: ... print(element) ... 0 1 2 3 10 11 12 13 20 21 22 23 30 31 32 33 40 41 42 43
另见
ndarrays 上的索引,索引例程(参考文档),newaxis
,ndenumerate
,indices
形状操作
改变数组的形状
数组的形状由每个轴上的元素数量确定:
>>> a = np.floor(10 * rg.random((3, 4))) >>> a array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]]) >>> a.shape (3, 4)
数组的形状可以使用各种命令来改变。请注意,以下三个命令都会返回一个修改后的数组,但不会改变原始数组:
>>> a.ravel() # returns the array, flattened array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.]) >>> a.reshape(6, 2) # returns the array with a modified shape array([[3., 7.], [3., 4.], [1., 4.], [2., 2.], [7., 2.], [4., 9.]]) >>> a.T # returns the array, transposed array([[3., 1., 7.], [7., 4., 2.], [3., 2., 4.], [4., 2., 9.]]) >>> a.T.shape (4, 3) >>> a.shape (3, 4)
从ravel
操作中生成的数组的元素顺序通常是“C-style”,即右边的索引“变化最快”,所以下标为a[0, 0]
之后的元素是a[0, 1]
。如果数组被重新整形为其他形状,这个数组仍然被视为“C-style”。NumPy 通常创建存储在这个顺序中的数组,所以ravel
通常不需要复制它的参数,但如果数组是通过对另一个数组切片或使用不寻常的选项创建的,则可能需要复制它。函数ravel
和reshape
还可以使用可选参数指示使用 FORTRAN-style 数组,其中最左边的索引变化得最快。
reshape
函数用修改后的形状返回其参数,而ndarray.resize
方法修改数组本身:
>>> a array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]]) >>> a.resize((2, 6)) >>> a array([[3., 7., 3., 4., 1., 4.], [2., 2., 7., 2., 4., 9.]])
如果在重整形操作中给出的维度为-1
,则其他维度会自动计算:
>>> a.reshape(3, -1) array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]])
另请参阅
ndarray.shape
, reshape
, resize
, ravel
将不同数组堆叠在一起
可以沿不同轴将多个数组堆叠在一起:
>>> a = np.floor(10 * rg.random((2, 2))) >>> a array([[9., 7.], [5., 2.]]) >>> b = np.floor(10 * rg.random((2, 2))) >>> b array([[1., 9.], [5., 1.]]) >>> np.vstack((a, b)) array([[9., 7.], [5., 2.], [1., 9.], [5., 1.]]) >>> np.hstack((a, b)) array([[9., 7., 1., 9.], [5., 2., 5., 1.]])
函数column_stack
将 1D 数组堆叠为列到 2D 数组中。它与 hstack
仅适用于 2D 数组:
>>> from numpy import newaxis >>> np.column_stack((a, b)) # with 2D arrays array([[9., 7., 1., 9.], [5., 2., 5., 1.]]) >>> a = np.array([4., 2.]) >>> b = np.array([3., 8.]) >>> np.column_stack((a, b)) # returns a 2D array array([[4., 3.], [2., 8.]]) >>> np.hstack((a, b)) # the result is different array([4., 2., 3., 8.]) >>> a[:, newaxis] # view `a` as a 2D column vector array([[4.], [2.]]) >>> np.column_stack((a[:, newaxis], b[:, newaxis])) array([[4., 3.], [2., 8.]]) >>> np.hstack((a[:, newaxis], b[:, newaxis])) # the result is the same array([[4., 3.], [2., 8.]])
另一方面,函数row_stack
对于任何输入数组都等同于vstack
。事实上,row_stack
是vstack
的别名:
>>> np.column_stack is np.hstack False >>> np.row_stack is np.vstack True
一般而言,对于维数大于两的数组,hstack
沿第二轴堆叠,vstack
沿第一轴堆叠,而 concatenate
允许使用一个可选参数,指定应该发生连接的轴的编号。
注意
在复杂情况下,r_
和 c_
对于通过沿一个轴堆叠数字创建数组很有用。它们允许使用范围文本 :
。
>>> np.r_[1:4, 0, 4] array([1, 2, 3, 0, 4])
当与数组一起使用时,r_
和 c_
在默认行为上类似于 vstack
和 hstack
,但允许使用可选参数指定沿其进行连接的轴的编号。
另请参阅
hstack
, vstack
, column_stack
, concatenate
, c_
, r_
将一个数组分割成几个较小的数组
使用 hsplit
,可以沿水平轴分割数组,可以指定要返回的等形状数组的数量,也可以在哪些列之后进行分割:
>>> a = np.floor(10 * rg.random((2, 12))) >>> a array([[6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.], [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]]) >>> # Split `a` into 3 >>> np.hsplit(a, 3) [array([[6., 7., 6., 9.], [8., 5., 5., 7.]]), array([[0., 5., 4., 0.], [1., 8., 6., 7.]]), array([[6., 8., 5., 2.], [1., 8., 1., 0.]])] >>> # Split `a` after the third and the fourth column >>> np.hsplit(a, (3, 4)) [array([[6., 7., 6.], [8., 5., 5.]]), array([[9.], [7.]]), array([[0., 5., 4., 0., 6., 8., 5., 2.], [1., 8., 6., 7., 1., 8., 1., 0.]])]
vsplit
沿垂直轴拆分,而 array_split
允许指定沿哪个轴拆分。
改变数组的形状
数组的形状由每个轴上的元素数量决定:
>>> a = np.floor(10 * rg.random((3, 4))) >>> a array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]]) >>> a.shape (3, 4)
使用各种命令可以更改数组的形状。请注意,以下三个命令都返回修改后的数组,但不会更改原始数组:
>>> a.ravel() # returns the array, flattened array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.]) >>> a.reshape(6, 2) # returns the array with a modified shape array([[3., 7.], [3., 4.], [1., 4.], [2., 2.], [7., 2.], [4., 9.]]) >>> a.T # returns the array, transposed array([[3., 1., 7.], [7., 4., 2.], [3., 2., 4.], [4., 2., 9.]]) >>> a.T.shape (4, 3) >>> a.shape (3, 4)
从 ravel
产生的数组中元素的顺序通常是“C-style”,即右边的索引“变化最快”,所以 a[0, 0]
后面的元素是 a[0, 1]
。如果将数组重新塑形为其他形状,那么数组将再次被视为“C-style”。NumPy 通常创建以此顺序存储的数组,因此 ravel
通常不需要复制其参数,但是如果数组由另一个数组的切片组成或通过使用不寻常的选项创建,则可能需要进行复制。函数 ravel
和 reshape
还可以通过可选参数指示使用 FORTRAN-style 数组,其中左侧索引变化最快。
reshape
函数返回带有修改形状的参数,而 ndarray.resize
方法修改数组本身:
>>> a array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]]) >>> a.resize((2, 6)) >>> a array([[3., 7., 3., 4., 1., 4.], [2., 2., 7., 2., 4., 9.]])
如果在重塑操作中一个维度给定为 -1
,则其他维度将自动计算:
>>> a.reshape(3, -1) array([[3., 7., 3., 4.], [1., 4., 2., 2.], [7., 2., 4., 9.]])
另请参阅
ndarray.shape
, reshape
, resize
, ravel
组合不同的数组
可以沿不同轴堆叠几个数组:
>>> a = np.floor(10 * rg.random((2, 2))) >>> a array([[9., 7.], [5., 2.]]) >>> b = np.floor(10 * rg.random((2, 2))) >>> b array([[1., 9.], [5., 1.]]) >>> np.vstack((a, b)) array([[9., 7.], [5., 2.], [1., 9.], [5., 1.]]) >>> np.hstack((a, b)) array([[9., 7., 1., 9.], [5., 2., 5., 1.]])
函数 column_stack
将 1D 数组依次堆叠为 2D 数组的列。它与 hstack
对于 2D 数组是等效的:
>>> from numpy import newaxis >>> np.column_stack((a, b)) # with 2D arrays array([[9., 7., 1., 9.], [5., 2., 5., 1.]]) >>> a = np.array([4., 2.]) >>> b = np.array([3., 8.]) >>> np.column_stack((a, b)) # returns a 2D array array([[4., 3.], [2., 8.]]) >>> np.hstack((a, b)) # the result is different array([4., 2., 3., 8.]) >>> a[:, newaxis] # view `a` as a 2D column vector array([[4.], [2.]]) >>> np.column_stack((a[:, newaxis], b[:, newaxis])) array([[4., 3.], [2., 8.]]) >>> np.hstack((a[:, newaxis], b[:, newaxis])) # the result is the same array([[4., 3.], [2., 8.]])
另一方面,row_stack
函数对任意输入数组等效于vstack
。事实上,row_stack
是vstack
的别名:
>>> np.column_stack is np.hstack False >>> np.row_stack is np.vstack True
一般来说,对于超过两个维度的数组,hstack
沿第二轴堆叠,vstack
沿第一轴堆叠,而concatenate
允许可选参数指定沿哪个轴进行连接。
注意
在复杂情况下,r_
和c_
用于通过沿一个轴堆叠数字来创建数组。它们允许使用区间字面值:
。
>>> np.r_[1:4, 0, 4] array([1, 2, 3, 0, 4])
当作为数组参数使用时,r_
和c_
与默认的行为下的vstack
和hstack
相似,但允许可选参数指定沿哪个轴连接。
另请参阅
hstack
,vstack
,column_stack
,concatenate
,c_
,r_
将一个数组分割为几个较小的数组
使用hsplit
,您可以沿水平轴拆分数组,要么指定返回的等尺寸数组的数量,要么指定分割应该发生的列:
>>> a = np.floor(10 * rg.random((2, 12))) >>> a array([[6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.], [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]]) >>> # Split `a` into 3 >>> np.hsplit(a, 3) [array([[6., 7., 6., 9.], [8., 5., 5., 7.]]), array([[0., 5., 4., 0.], [1., 8., 6., 7.]]), array([[6., 8., 5., 2.], [1., 8., 1., 0.]])] >>> # Split `a` after the third and the fourth column >>> np.hsplit(a, (3, 4)) [array([[6., 7., 6.], [8., 5., 5.]]), array([[9.], [7.]]), array([[0., 5., 4., 0., 6., 8., 5., 2.], [1., 8., 6., 7., 1., 8., 1., 0.]])]
vsplit
沿垂直轴分割,而array_split
允许指定沿哪个轴进行分割。
复制和视图
在操作和操作数组时,它们的数据有时会复制到新数组中,有时不会。这通常是初学者困惑的原因。有三种情况:
没有任何复制
简单赋值不会复制对象或其数据。
>>> a = np.array([[ 0, 1, 2, 3], ... [ 4, 5, 6, 7], ... [ 8, 9, 10, 11]]) >>> b = a # no new object is created >>> b is a # a and b are two names for the same ndarray object True
Python 将可变对象作为引用传递,因此函数调用不会复制。
>>> def f(x): ... print(id(x)) ... >>> id(a) # id is a unique identifier of an object 148293216 # may vary >>> f(a) 148293216 # may vary
视图或浅复制
不同的数组对象可以共享相同的数据。view
方法创建一个新的数组对象,它查看相同的数据。
>>> c = a.view() >>> c is a False >>> c.base is a # c is a view of the data owned by a True >>> c.flags.owndata False >>> >>> c = c.reshape((2, 6)) # a's shape doesn't change >>> a.shape (3, 4) >>> c[0, 4] = 1234 # a's data changes >>> a array([[ 0, 1, 2, 3], [1234, 5, 6, 7], [ 8, 9, 10, 11]])
对数组进行切片会返回一个视图:
>>> s = a[:, 1:3] >>> s[:] = 10 # s[:] is a view of s. Note the difference between s = 10 and s[:] = 10 >>> a array([[ 0, 10, 10, 3], [1234, 10, 10, 7], [ 8, 10, 10, 11]])
深复制
copy
方法会完全复制数组及其数据。
>>> d = a.copy() # a new array object with new data is created >>> d is a False >>> d.base is a # d doesn't share anything with a False >>> d[0, 0] = 9999 >>> a array([[ 0, 10, 10, 3], [1234, 10, 10, 7], [ 8, 10, 10, 11]])
有时在切片之后,原始数组不再需要时,应该调用copy
。例如,假设a
是一个很大的中间结果,而最终结果b
只包含a
的一小部分,那么在用切片构造b
时应该进行深复制:
>>> a = np.arange(int(1e8)) >>> b = a[:100].copy() >>> del a # the memory of ``a`` can be released.
如果使用b = a[:100]
,a
被b
引用,并且即使执行del a
,a
也会在内存中保留。
函数和方法概述
以下是一些有用的 NumPy 函数和方法名称,按类别排序。请参见 Routines 获取完整列表。
数组创建
arange
,array
,copy
,empty
,empty_like
,eye
,fromfile
,fromfunction
,identity
,linspace
,logspace
,mgrid
,ogrid
,ones
,ones_like
,r_
,zeros
,zeros_like
转换
ndarray.astype
,atleast_1d
,atleast_2d
,atleast_3d
,mat
操作
array_split
, column_stack
, concatenate
, diagonal
, dsplit
, dstack
, hsplit
, hstack
, ndarray.item
, newaxis
, ravel
, repeat
, reshape
, resize
, squeeze
, swapaxes
, take
, transpose
, vsplit
, vstack
问题
all
, any
, nonzero
, where
排序
argmax
, argmin
, argsort
, max
, min
, ptp
, searchsorted
, sort
操作
choose
,compress
,cumprod
,cumsum
,inner
,ndarray.fill
,imag
,prod
,put
,putmask
,real
,sum
基本统计学
cov
,mean
,std
,var
基本线性代数
cross
,dot
,outer
,linalg.svd
,vdot
完全不复制
简单赋值不会复制对象或其数据。
>>> a = np.array([[ 0, 1, 2, 3], ... [ 4, 5, 6, 7], ... [ 8, 9, 10, 11]]) >>> b = a # no new object is created >>> b is a # a and b are two names for the same ndarray object True
Python 将可变对象传递为引用,所以函数调用不会复制。
>>> def f(x): ... print(id(x)) ... >>> id(a) # id is a unique identifier of an object 148293216 # may vary >>> f(a) 148293216 # may vary
查看或浅复制
不同的数组对象可以共享相同的数据。view
方法创建一个查看相同数据的新数组对象。
>>> c = a.view() >>> c is a False >>> c.base is a # c is a view of the data owned by a True >>> c.flags.owndata False >>> >>> c = c.reshape((2, 6)) # a's shape doesn't change >>> a.shape (3, 4) >>> c[0, 4] = 1234 # a's data changes >>> a array([[ 0, 1, 2, 3], [1234, 5, 6, 7], [ 8, 9, 10, 11]])
对数组进行切片会返回一个视图:
>>> s = a[:, 1:3] >>> s[:] = 10 # s[:] is a view of s. Note the difference between s = 10 and s[:] = 10 >>> a array([[ 0, 10, 10, 3], [1234, 10, 10, 7], [ 8, 10, 10, 11]])
深度复制
copy
方法完全复制数组及其数据。
>>> d = a.copy() # a new array object with new data is created >>> d is a False >>> d.base is a # d doesn't share anything with a False >>> d[0, 0] = 9999 >>> a array([[ 0, 10, 10, 3], [1234, 10, 10, 7], [ 8, 10, 10, 11]])
如果原始数组不再需要,有时应在切片后调用copy
。例如,假设a
是一个巨大的中间结果,最终结果b
只包含a
的一小部分,那么在使用切片构建b
时应进行深拷贝:
>>> a = np.arange(int(1e8)) >>> b = a[:100].copy() >>> del a # the memory of ``a`` can be released.
如果使用b = a[:100]
,a
被b
引用并且即使执行del a
,它也将在内存中持久存在。
函数和方法概览
这是一些有用的 NumPy 函数和方法名称按类别排序的列表。完整的列表请参见 Routines。
创建数组
arange
, array
, copy
, empty
, empty_like
, eye
, fromfile
, fromfunction
, identity
, linspace
, logspace
, mgrid
, ogrid
, ones
, ones_like
, r_
, zeros
, zeros_like
转换
ndarray.astype
, atleast_1d
, atleast_2d
, atleast_3d
, mat
操作
array_split
, column_stack
, concatenate
, diagonal
, dsplit
, dstack
, hsplit
, hstack
, ndarray.item
, newaxis
, ravel
, repeat
, reshape
, resize
, squeeze
, swapaxes
, take
, transpose
, vsplit
, vstack
问题
all
, any
, nonzero
, where
排序
argmax
, argmin
, argsort
, max
, min
, ptp
, searchsorted
, sort
操作
choose
, compress
, cumprod
, cumsum
, inner
, ndarray.fill
, imag
, prod
, put
, putmask
, real
, sum
基本统计
cov
, mean
, std
, var
基本线性代数
cross
, dot
, outer
, linalg.svd
, vdot
NumPy 1.26 中文官方指南(一)(4)https://developer.aliyun.com/article/1510636