numpy是一个python和矩阵相关的库,在机器学习中非常有用,记录下numpy的基本用法
numpy的数组类叫做ndarray也叫做数组,跟python标准库中的array.array不同,后者只处理一维的数组而且提供很少的函数,numpy中有更多重要的属性
分别是
ndarray.ndim 该数组的维度,轴的数量
ndarray.shape 该数组的尺寸二维数组(m, n)m行n列,如果是三维或者以上的会包含其维度即(维度,m,n)
ndarray.size 数组中所有元素的数量
ndarray.dtype 数组中元素的类型
ndarray.itemsize 数组中每个元素的字节大小,float64中此项为64/8,int32中此项为32/8
ndarray.data 数组中包含的数据的缓冲区,一般不使用,都是使用索引来访问元素
数组的创建
np.array([2,3,4])
np.array([[2,3,4],[3,4,5]], dtype=np.int32)
np.zeros((3,4))创建一个全零的3*4数组
np.ones(3,4)创建一个全一的3*4数组
np.empty((2,3))创建一个数组,初始内容随机,取决内存的状态,默认创建的数组类型为float64
使用arange函数可以创建一个序列,类似于列表的数组
np.arange(10, 30, 5)从10到30以5为步长创建一个数组
如果不知道步长的话可以使用linspace
np.linspace(0,2,9)从0到2平均产生9个数
reshape函数可以将数组转换成指定维度,行,列的数组
np.arange(100).reshape(10,10)将一个一维的0-99的数组转换为10个0-9的数组
基础的操作
>>> 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)
两个矩阵相乘,使用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]])
使用+=或者*=会修改已经存在的数组而不是创建一个新的数组
sum函数计算数组总和
min函数求最小
max函数求最大
如果想求行中总和或者列中总和可以使用axis参数
sum(axis=0)求列总和,axis=1求行总和
max,min类似
>>> 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等
一维数组可以被索引,切片,迭代,就像其他和列表一样的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]=b[-1, :]即取出最后一行的所有元素
对多维数组来说,迭代只迭代一个(轴)维度
>>> 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]
如果要获取所有元素
>>> 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
连接不同的数组
np.vstack()添加到下一行
np.hstack()添加到同行尾部
>>> 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.]])
分离数组元素
np.hsplit()
np.vsplit()
>>> 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.]])]
数组的复制和查看
当操作和操作数组时,他们的数据有时会被复制到一个新的数组中,这通常是初学者混淆的来源。有三种情况
>>> 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)
赋值语句并不等于创建一个新的数组,而是对旧数组的引用
查看与浅拷贝
不同的数组对象可以享有相同的数据,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]])
对数组切片返回一个数组的view
>>> 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]])
view和切片得到的数组如果改变,源数组也会改变
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]])
参考自官方文档
https://docs.scipy.org/doc/numpy-dev/user/quickstart.html