NumPy是Python中科学计算的基础包。它是一个Python库,提供多维数组对象,各类派生对象(如掩码数组和矩阵),以及用于数组快速操做的各类API,有包括数学、逻辑、形状操做、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。html
NumPy包的核心是 ndarray 对象。它封装了python原生的同数据类型的 n 维数组,为了保证其性能优良,其中有许多操做都是代码在本地进行编译后执行的。python
NumPy数组 和 原生Python Array(数组)之间有几个重要的区别:数组
shape
将是 (n,m)
。所以,shape
元组的长度就是rank或维度的个数 ndim
。shape
的元素的乘积。float64
类型的数组的 itemsize
为8(=64/8),而 complex32
类型的数组的 itemsize
为4(=32/8)。它等于 ndarray.dtype.itemsize
。一个例子less
>>> 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) <type 'numpy.ndarray'> >>> b = np.array([6, 7, 8]) >>> b array([6, 7, 8]) >>> type(b) <type 'numpy.ndarray'>
有几种方法能够建立数组。dom
例如,你可使用array函数从常规Python列表或元组中建立数组。获得的数组的类型是从Python列表中元素的类型推导出来的。ide
>>> 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')
能够在建立时显式指定数组的类型:函数
>>> c = np.array( [ [1,2], [3,4] ], dtype=complex ) >>> c array([[ 1.+0.j, 2.+0.j], [ 3.+0.j, 4.+0.j]])
函数zeros
建立一个由0组成的数组,函数 ones
建立一个完整的数组,函数empty
建立一个数组,其初始内容是随机的,取决于内存的状态。默认状况下,建立的数组的dtype是 float64
类型的。工具
>>> 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 ) # dtype can also be specified 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) ) # uninitialized, output may vary array([[ 3.73603959e-262, 6.02658058e-154, 6.55490914e-260], [ 5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])
为了建立数字组成的数组,NumPy提供了一个相似于range
的函数,该函数返回数组而不是列表。布局
>>> 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])
当您打印数组时,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]]]
数组上的算术运算符会应用到 元素 级别。下面是建立一个新数组并填充结果的示例:
>>> 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]])
某些操做(例如+=
和 *=
)会更直接更改被操做的矩阵数组而不会建立新矩阵数组。
>>> a = np.ones((2,3), dtype=int) >>> b = np.random.random((2,3)) >>> a *= 3 >>> a array([[3, 3, 3], [3, 3, 3]]) >>> b += a >>> b array([[ 3.417022 , 3.72032449, 3.00011437], [ 3.30233257, 3.14675589, 3.09233859]]) >>> a += b # b is not automatically converted to integer type Traceback (most recent call last): ... TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
许多一元操做,例如计算数组中全部元素的总和,都是做为ndarray
类的方法实现的。
>>> a = np.random.random((2,3)) >>> a array([[ 0.18626021, 0.34556073, 0.39676747], [ 0.53881673, 0.41919451, 0.6852195 ]]) >>> a.sum() 2.5718191614547998 >>> a.min() 0.1862602113776709 >>> a.max() 0.6852195003967595
默认状况下,这些操做适用于数组,就像它是一个数字列表同样,不管其形状如何。可是,经过指定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.])
一维的数组能够进行索引、切片和迭代操做的,就像 列表 和其余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]) >>> a[:6:2] = -1000 # equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -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.)) ... nan 1.0 nan 3.0 nan 5.0 6.0 7.0 8.0 9.0
多维的数组每一个轴能够有一个索引。这些索引以逗号分隔的元组给出:
>>> 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
是rank为的5数组(即,它具备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]])
对多维数组进行 迭代(Iterating) 是相对于第一个轴完成的:
>>> 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
一个数组的形状是由每一个轴的元素数量决定的:
>>> a = np.floor(10*np.random.random((3,4))) >>> a array([[ 2., 8., 0., 6.], [ 4., 5., 1., 1.], [ 8., 9., 3., 6.]]) >>> a.shape (3, 4)
可使用各类命令更改数组的形状。请注意,如下三个命令都返回一个修改后的数组,但不会更改原始数组:
>>> a.ravel() # returns the array, flattened array([ 2., 8., 0., 6., 4., 5., 1., 1., 8., 9., 3., 6.]) >>> a.reshape(6,2) # returns the array with a modified shape array([[ 2., 8.], [ 0., 6.], [ 4., 5.], [ 1., 1.], [ 8., 9.], [ 3., 6.]]) >>> a.T # returns the array, transposed array([[ 2., 4., 8.], [ 8., 5., 9.], [ 0., 1., 3.], [ 6., 1., 6.]]) >>> a.T.shape (4, 3) >>> a.shape (3, 4)
由 ravel() 产生的数组中元素的顺序一般是“C风格”,也就是说,最右边的索引“变化最快”,所以[0,0]以后的元素是[0,1] 。若是将数组从新整形为其余形状,则该数组将被视为“C风格”。NumPy一般建立按此顺序存储的数组,所以 ravel() 一般不须要复制其参数,但若是数组是经过获取另外一个数组的切片或使用不常见的选项建立的,则可能须要复制它。还可使用可选参数指示函数 ravel() 和 reshape(),以使用FORTRAN样式的数组,其中最左边的索引变化最快。
该reshape
函数返回带有修改形状的参数,而该 ndarray.resize
方法会修改数组自己:
>>> a array([[ 2., 8., 0., 6.], [ 4., 5., 1., 1.], [ 8., 9., 3., 6.]]) >>> a.resize((2,6)) >>> a array([[ 2., 8., 0., 6., 4., 5.], [ 1., 1., 8., 9., 3., 6.]])
若是在 reshape 操做中将 size 指定为-1,则会自动计算其余的 size 大小:
>>> a.reshape(3,-1) array([[ 2., 8., 0., 6.], [ 4., 5., 1., 1.], [ 8., 9., 3., 6.]])
几个数组能够沿不一样的轴堆叠在一块儿,例如:
>>> a = np.floor(10*np.random.random((2,2))) >>> a array([[ 8., 8.], [ 0., 0.]]) >>> b = np.floor(10*np.random.random((2,2))) >>> b array([[ 1., 8.], [ 0., 4.]]) >>> np.vstack((a,b)) array([[ 8., 8.], [ 0., 0.], [ 1., 8.], [ 0., 4.]]) >>> np.hstack((a,b)) array([[ 8., 8., 1., 8.], [ 0., 0., 0., 4.]])
使用hsplit
,能够沿数组的水平轴拆分数组,方法是指定要返回的形状相等的数组的数量,或者指定应该在其以后进行分割的列:
>>> a = np.floor(10*np.random.random((2,12))) >>> a array([[ 9., 5., 6., 3., 6., 8., 0., 7., 9., 7., 2., 7.], [ 1., 4., 9., 2., 2., 1., 0., 6., 2., 2., 4., 0.]]) >>> np.hsplit(a,3) # Split a into 3 [array([[ 9., 5., 6., 3.], [ 1., 4., 9., 2.]]), array([[ 6., 8., 0., 7.], [ 2., 1., 0., 6.]]), array([[ 9., 7., 2., 7.], [ 2., 2., 4., 0.]])] >>> np.hsplit(a,(3,4)) # Split a after the third and the fourth column [array([[ 9., 5., 6.], [ 1., 4., 9.]]), array([[ 3.], [ 2.]]), array([[ 6., 8., 0., 7., 9., 7., 2., 7.], [ 2., 1., 0., 6., 2., 2., 4., 0.]])]
vsplit沿垂直轴分割,并array_split容许指定要分割的轴。
当计算和操做数组时,有时会将数据复制到新数组中,有时则不会。这一般是初学者混淆的根源。有三种状况:
简单分配不会复制数组对象或其数据。
>>> a = np.arange(12) >>> b = a # no new object is created >>> b is a # a and b are two names for the same ndarray object True >>> b.shape = 3,4 # changes the shape of a >>> a.shape (3, 4)
Python将可变对象做为引用传递,所以函数调用不会复制。
>>> def f(x): ... print(id(x)) ... >>> id(a) # id is a unique identifier of an object 148293216 >>> f(a) 148293216
不一样的数组对象能够共享相同的数据。该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.shape = 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] # spaces added for clarity; could also be written "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
也会在内存中持久存在。
广播容许通用功能以有意义的方式处理不具备彻底相同形状的输入。
广播的第一个规则是,若是全部输入数组不具备相同数量的维度,则将“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] # i.e., a[ : , j] array([[[ 2, 1], [ 3, 3]], [[ 6, 5], [ 7, 7]], [[10, 9], [11, 11]]])
固然,咱们能够按顺序(好比列表)放入i
,j
而后使用列表进行索引。
>>> l = [i,j] >>> a[l] # equivalent to a[i,j] array([[ 2, 5], [ 7, 11]])
可是,咱们不能经过放入i
和j
放入数组来实现这一点,由于这个数组将被解释为索引a的第一个维度。
>>> s = np.array( [i,j] ) >>> a[s] # not what we want Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: index (3) out of range (0<=index<=2) in dimension 0 >>> >>> a[tuple(s)] # same as a[i,j] 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]]) >>> >>> ind = data.argmax(axis=0) # index of the maxima for each series >>> ind array([2, 0, 3, 1]) >>> >>> time_max = time[ind] # times corresponding to the maxima >>> >>> 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 ): ... """Returns an image of the Mandelbrot fractal of size (h,w).""" ... y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ] ... c = x+y*1j ... z = c ... divtime = maxit + np.zeros(z.shape, dtype=int) ... ... for i in range(maxit): ... z = z**2 + c ... diverge = z*np.conj(z) > 2**2 # who is diverging ... div_now = diverge & (divtime==maxit) # who is diverging now ... divtime[div_now] = i # note when ... z[diverge] = 2 # avoid diverging too much ... ... return divtime >>> plt.imshow(mandelbrot(400,400)) >>> plt.show()
使用布尔值进行索引的第二种方法更相似于整数索引; 对于数组的每一个维度,咱们给出一个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_
函数可用于组合不一样的向量,以便得到每一个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] 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相比,这个版本的reduce的优势是它利用了广播规则 ,以免建立一个参数数组,输出的大小乘以向量的数量。
>>> import numpy as np >>> a = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> print(a) [[ 1. 2.] [ 3. 4.]] >>> a.transpose() array([[ 1., 3.], [ 2., 4.]]) >>> np.linalg.inv(a) array([[-2. , 1. ], [ 1.5, -0.5]]) >>> u = np.eye(2) # unit 2x2 matrix; "eye" represents "I" >>> u array([[ 1., 0.], [ 0., 1.]]) >>> j = np.array([[0.0, -1.0], [1.0, 0.0]]) >>> j @ j # matrix product array([[-1., 0.], [ 0., -1.]]) >>> np.trace(u) # trace 2.0 >>> y = np.array([[5.], [7.]]) >>> np.linalg.solve(a, y) array([[-3.], [ 4.]]) >>> np.linalg.eig(j) (array([ 0.+1.j, 0.-1.j]), array([[ 0.70710678+0.j , 0.70710678-0.j ], [ 0.00000000-0.70710678j, 0.00000000+0.70710678j]]))
Parameters: square matrix Returns The eigenvalues, each repeated according to its multiplicity. The normalized (unit "length") eigenvectors, such that the column ``v[:,i]`` is the eigenvector corresponding to the eigenvalue ``w[i]`` .
这里咱们列出一些简短有用的提示。
要更改数组的尺寸,您能够省略其中一个尺寸,而后自动推导出尺寸:
>>> a = np.arange(30) >>> a.shape = 2,-1,3 # -1 means "whatever is needed" >>> a.shape (2, 5, 3) >>> a 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这是很简单:若是x
和y
你只须要作两个相同长度的向量m=[x;y]
。在此NumPy的经过功能的工做原理column_stack
,dstack
,hstack
和vstack
,视维在堆叠是必需要作的。例如:
x = np.arange(0,10,2) # x=([0,2,4,6,8]) y = np.arange(5) # y=([0,1,2,3,4]) m = np.vstack([x,y]) # m=([[0,2,4,6,8], # [0,1,2,3,4]]) xy = np.hstack([x,y]) # xy =([0,2,4,6,8,0,1,2,3,4])
这些函数背后的逻辑在两个以上的维度上可能很奇怪。
histogram
应用于数组的NumPy 函数返回一对向量:数组的直方图和bin的向量。注意: matplotlib
还有一个构建直方图的功能(hist
在Matlab中称为),与NumPy中的直方图不一样。主要区别在于pylab.hist
自动绘制直方图,而 numpy.histogram
只生成数据。
>>> import numpy as np >>> import matplotlib.pyplot as plt >>> # Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2 >>> mu, sigma = 2, 0.5 >>> v = np.random.normal(mu,sigma,10000) >>> # Plot a normalized histogram with 50 bins >>> plt.hist(v, bins=50, density=1) # matplotlib version (plot) >>> plt.show()
>>> # 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) >>> plt.show()