本文乃Numpy Quickstart tutorial的翻译版本(并非完全翻译,翻译君为本人),英语能力足够的童鞋请阅读原文~,如果您觉得本文对您有帮助的话不要忘记点个赞哦!
一 预先准备
在阅读本文之前,请先确保您已经有了一些python基础,如果没有的话,请看Python Tutorial,安装在此跳过。
二 基础
numpy的操作对象通常是齐次的多维数组,数组的每一个元素的类型应当一致(比如全为int,float等等),numpy中,多维数组的维度被称为轴(比如三维数组之于XYZ),轴上以循秩(rank)访问。
譬如在三维空间中一个点[1,2,1],该点的坐标可以看做是一个rank为1的数组(一维数组),数组长度3
而下列所示为rank=2(二维数组),第一个维度长度为2,第二个维度长度为3
[[ 1., 0., 0.],
[ 0., 1., 2.]]
Numpy的数组类称为ndarray,注意numpy.array和python标准库中的array并不一样,后者只提供一维数组及其操作。下面列出numpy的一些重要接口:
ndarray.ndim
数组的维度,也称数组的轴(axes)的数量。
ndarray.shape
数组的尺寸。返回一个整数元组,表示数组中每个维度上,数组含有多少元素。对于具有n行m列的矩阵,形状将是(n,m)。显然这个元组的长度是数组的维度ndarray.ndim
ndarray.size
数组元素的总数。等于数组尺寸中所有值的乘积,对于具有n行m列的矩阵,就是n*m
ndarray.dtype
数组中元素的类型。可以使用标准的Python中定义的类型创建,或指定其他的dtype类型。此外,NumPy提供了一些它自己的类型。譬如: numpy.int32,numpy.int16,numpy.float64
ndarray.itemsize
数组中每个元素的字节大小。例如,float64类型的元素大小为8(= 64/8),而complex32类型中的项目大小为4(= 32/8)。相当于ndarray.dtype.itemsize。
ndarray.data
该缓冲区包含数组的实际元素。通常,我们不需要使用它,因为我们将使用循秩访问访问数组中的元素。
例子:
>>> 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'>
三 数组的创建
下面我们就来介绍如何创建数组。
方法一:使用python 列表或者元组创建,array的dtype将会取决于您输入元素的类型。如果您输入的数字都为int或者都为float,那么array的类型也将是这个。
>>> 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
>>> a = np.array([1,2,3,4]) # RIGHT
可以将array转换成二维数组,形似[array(),array(),array().........]。以同样的方法可以创建三维,乃至更多维度的数组
>>> b = np.array([(1.5,2,3), (4,5,6)]) # 注意到这里混用了int和float,最终全部转换成了float
>>> 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]])
array的初始化:创建完成后数组内部元素是未知的,尽量应当初始化它。下面介绍几个用于初始化的函数
1.zeros,创建一个一定大小的,内部元素全部填充为0的数组
2.ones,创建一个一定大小的,内部元素全部填充为1的数组
3.empty,创建一个一定大小的,内部元素全部为随机数的数组,默认类型为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同样提供了可以返回范围的函数,
np.arange( lo, hi, delta ) # 从lo开始直到hi(不包括hi),每隔delta给一个数
>>> 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也提供了相似功能的函数,这个函数可以规定将lo到hi平分为多少步走完。
>>> 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. ])
这一函数可以很简便地用于绘函数图,并规定精度,代码如下:
>>> from numpy import pi
>>> x = np.linspace( 0, 2*pi, 100 ) # useful to evaluate function at lots of points
>>> f = np.sin(x)
四 数组的打印
如果您要打印多维数组,numpy将以如下规则进行:
1.从左到右打印最后一个维度的元素
2.从上到下打印倒数第二个轴的元素
3.剩下的维度一样从上到下,只不过每一个矩阵都和下一个分开打印
总之,一维数组打印为一行,二维数组打印为一个矩阵,三维数组打印为矩阵列表
>>> 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]]]
注意:如果数组过于巨大,比如上万行,上万列等等。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这么做,强制打印整个数组,可以输入下列内容以禁止打印角点。
>>> np.set_printoptions(threshold='nan')
五 基础操作
1.数组的运算。当进行数组的运算时,将会创建一个新的数组来保存运算结果。
相同大小的数组之间可以进行:
(1)加减操作,每个元素都被加减;
(2)平方(写作**),sin()等函数操作,其中的每个元素都进行该运算,并填入结果中
(3)bool运算,每个元素都进行这样的判断,在结果中填入T/F
>>> 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], dtype=bool)
numpy中,*表示数组对应位置的元素相乘,矩阵乘法要使用.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.dot(B) # matrix product 矩阵乘法 array([[5, 4], [3, 4]]) >>> np.dot(A, 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'
对于那些创建新的数组来保存结果的运算,当两种不同类型的元素运算时,结果自动变成两种中更精确那种类型,比如float+complex->complex
>>> 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'
numpy提供求所有元素的sum(),min(),max(),mean()等一元运算,这些都需要调用numpy,这些操作默认是对数组的一切元素进行,不论数组的形状,维度
>>> 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
>>> a = np.array([[1, 2], [3, 4]]) >>> np.mean(a) 2.5
如果要对特定的维度上进行上述操作,请指定维度,即sum(axis= ),注意轴的序列是列axis=0,行axis=1。
>>> 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]])
>>> a = np.array([[1, 2], [3, 4]]) >>> np.mean(a) 2.5 >>> np.mean(a, axis=0) array([ 2., 3.]) >>> np.mean(a, axis=1) array([ 1.5, 3.5])
其他操作:numpy还支持sin cos exp sqrt等常规函数,这些函数对数组里的所有元素进行操作
>>> 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的list相似
>>> 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多维数组的元素具有一个多维的索引,通过元组[a,b],(a行b列,ab均为0-index)可以访问之,切片也是一样
>>> 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,:]
# 维度取值应当为0-n的值,但是python允许超过这个范围,并且取出mod n 的秩 ,-1表示最后一行 array([40, 41, 42, 43])
如果觉得太多的:,:,:麻烦,可以用...(三个点)代替,其中的维度将使用尽量多的:,代替。
比如B[1,...],则代表第一片矩阵的全部。
>>> 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
第一部分到此结束,如果觉得这一部分对您有帮助的话,请点赞。如果我的翻译哪里不妥,还请指出。
2018/3/23