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