Numpy 入门

293 阅读8分钟

简介

numpy是python的一个开源的数值计算库,该库可以用来存储和处理大型矩阵,比python的自带的list和tuple处理效率更高。

numpy的创建和引入

numpy是python的一个开源库,安装好python后可以采用如下的方式,安装numpy。

    pip3 install numpy

代码中引入numpy也很简单,采用如下方式就可以了。

    import numpy as np

矩阵的创建

常规的方法:

  1. 一维矩阵
    array1=np.array([1,2,3,4,5])
  1. 二维矩阵
    array1=np.array([[1,2,3,4,5],[2,3,4,5,6]])
  1. 三维矩阵
    array1=np.array([[[1,2,3,4,5],[2,3,4,5,6]]])

可以看出创建什么样可以将相关矩阵直接传入就可以了。

快捷的方法是

  1. 创建全0矩阵,其中(2,3)表示生成的是2行,3列的矩阵
	x=np.zeros((2,3))  
	print(x)    
	#输出内容
	#[[0,0,0]
	# [0,0,0]]
  1. 创建全1矩阵,其中(2,3)表示生成的是2行,3列的矩阵
	x=np.ones((2,3)) 
	print(x)
	#输出内容
	#[[1,1,1]
	# [1,1,1]]
  1. 创建一个empty矩阵,需要说明该方法生成不是真正意义上的empty矩阵,而是不限接近于0的矩阵,其中(2,3)表示生成的是2行,3列的矩阵
	empty=np.empty((2,3)) 
	print(empty)
	#输出内容
    #[[0.00000000e+000   2.31584192e+077   1.48219694e-323]
    # [nan               2.13839732e-314   4.17203541e-309]]

4,创建一个full矩阵,其中(2,2)表示生成的为2行,2列的矩阵,7为矩阵数据都是为7.

    x=np.full((2,2),7)
	print(x)
	#输出内容
	#[[7 7]
    #[7 7]]
  1. 创建单元矩阵,其中2表示的是2*2的矩阵
	x=np.eye(2)
	print(x)
	#输出内容
	#[[ 1.  0.]
    # [ 0.  1.]]
  1. 创建指定最大最小值和步长,形状的矩阵
	x=np.arange(10).reshape(2,5) #从0,9的2行5列的矩阵
	print(x)
    #输出内容
    #[[0 1 2 3 4]
    # [5 6 7 8 9]]

	x=np.arange(4,12).reshape(2,4) #从4,11的2行5列的矩阵
	print(x)
	#输出内容
	#[[ 4  5  6  7]
    # [ 8  9 10 11]]

	x=np.arange(1,20,3).reshape(1,7) #从1,20 步长为3的的1行7列的矩阵
	print(x)
    #输出内容
    #[[ 1  4  7 10 13 16 19]]
  1. 创建指定形状的随机矩阵
	x=np.random.random((3,2)) #生成3行2列,0到1之间随机数的矩阵
	print(x)
	#输出内容:
	#[[ 0.02877225  0.0536815 ]
    # [ 0.95767806  0.63741724]
    # [ 0.10975063  0.78859285]]
	x=np.random.randint(0,10,(3,2)) #生成3行2列,0到10之间随机整数的矩阵
	print(x)
	#输出内容:
	#[[7 9]
    # [1 8]
    # [6 3]]
	x=np.random.normal(size=(3,2)) #生成3行2列,符合正态分布的矩阵
	print(x)
	#输出内容:
	#[[ 1.24485604 -0.73626677]
    # [ 1.3671711  -0.24442532]
    # [-1.08691618 -0.6656498 ]]

矩阵的访问

切片访问:numpy矩阵可以使用类似python切片的方式,访问矩阵内容。但是矩阵是多维的,因此指定每个维度指定好切片。

    x=np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16])
    y=x[:3,1:3] 
    print(y)
    #输出内容(输出0,1,2行,1,2列(行列都是以0开头))
    #[[ 2  3]
    # [ 6  7]
    # [10 11]]
    print(x[2,3])
    #输出内容(输出1行,第2列的数值(行列都是以0开头))
    #12
    y[0, 0] = 77
	print(x[0, 1])
	#输出内容
	#77
	#发现修改了y的值,导致了x值发生了改变。原因是y[0, 0]和x[0, 1]是同一个值,两者有一个改变,另一个值会跟着发生改变。

整型数组访问:采用整型数组访问矩阵

    x=np.array([[1,2], [3, 4], [5, 6]])
	print(x[[0,1,2],[0,1,0]])
	#输出内容
	#[1 4 5]
	print(np.array([x[0,0],x[1,1],x[2,0]]))
	#输出内容
	#[1 4 5]

可以看出这个方式获得值是一样的。第二种方法比较简单,是典型的切片访问的方式。第一种方式是传入了两个数组[0,1,2]和[0,1,0],numpy在方式访问矩阵时将两个数组解析为(0,0),(1,1),(2,0)这三个组合访问矩阵。按照此思路,如下code输出如下。

	x=np.array([[1,2], [3, 4], [5, 6]])
	print(x[[0, 1], [1, 0]])
	#输出内容:
	#[2 3]
	print(np.array([x[0,1],x[1,0]]))
	#输出内容:
	#[2 3]

布尔型数组访问:布尔型数组可以访问矩阵中满足某些条件的元素

    x=np.array([[1,2], [3, 4], [5, 6]])
	bool_idx=(x>2) 
	print(bool_idx)
	#输出内容:
	#[[False False]
    # [True  True]
    # [True  True]]
    print(x[bool_idx])
    #输出内容:
    #[3 4 5 6]
    print(x[x>2])
    #输出内容:
    #[3 4 5 6]

矩阵的计算

基础运算

    x = np.array([[1, 2], [3, 4]])
	y = np.array([[5, 6], [7, 8]])

	print(np.add(x,y))   #np.add(x,y)和(x+y)等价
	#输出内容:
    #[[ 6  8]
    # [10 12]]
    
	print(np.subtract(x,y))  #np.subtract(x,y)和(x-y)等价
	#输出内容:
	#[[-4 -4]
    # [-4 -4]]
    
	print(np.multiply(x,y))  #np.multiply(x,y)和(x*y)等价
	#输出内容:
    #[[ 5 12]
    # [21 32]]
    
	print(np.divide(x,y))   #np.divide(x,y)和(x/y)等价
    #输出内容:
    #[[ 0.2         0.33333333]
    # [ 0.42857143  0.5       ]]
    
	print(np.sqrt(x))  #矩阵中每个元素的开方
	#输出内容:
	#[[ 1.          1.41421356]
    # [ 1.73205081  2.        ]]

	print(np.sum(x)) #矩阵x所有数据累加 等价于x.sum()
	#输出内容:
	#10
	
	print(np.sum(x,axis=0)) #矩阵x列相累加 等价于x.sum(axis=0)
	#输出内容:
	#[4 6]
	
	print(np.sum(x,axis=1)) #矩阵y行累加  等价于等价于x.sum(axis=1)
	#输出内容:
	#[3 7]
	

note:类似还有求平均值(np.mean(x)或x.mean()),求最小值索引(np.argmin(x)或x.argmin(x))等方法

矩阵乘法。如上述代码我们可以看到采用multiply或*相乘,是将每个元素相乘并不是矩阵乘法。因此采用如下方法进行矩阵乘法

    a = np.array([[1, 2], [3, 4]])
	b = np.array([11, 12])
	print(a.dot(b)) # 等价于np.dot(a,b)
	#输出内容:
	#[35 81]

矩阵转置。矩阵的转置是比较线性代数中比较常见一个计算方式

    a = np.array([[1, 2], [3, 4]])
    print(a)
    #输出内容:
    #[[1 2]
    # [3 4]]
	print(a.T)  #等价于np.transpose(a)
	#输出内容:
	#[[1 3]
    # [2 4]]

note:需要指出如果矩阵是[1,2,3]这种一维矩阵,转置矩阵和原矩阵输出是一致的。

矩阵的参数

使用numpy可以获得创建矩阵的相关参数,主要获得参数的方法如下。 ndim 矩阵的维度

    x=np.array([1,2,3,4,5])
	y=np.array([[1,2,3],[4,5,6]])
	print('x number of dim:',x.ndim)
	#输出内容:
	#x number of dim:1
	print('y number of dim:',y.ndim)
	#输出内容:
	#y number of dim:2

shape 矩阵的形状

    x=np.array([1,2,3,4,5])
	y=np.array([[1,2,3],[4,5,6]])
	print('x shape:',x.shape)
	#输出内容:x shape : (5,)
	print('y shape:',y.shape)
	#输出内容:y shape : (2, 3)

size 矩阵的大小

    x=np.array([1,2,3,4,5])
	y=np.array([[1,2,3],[4,5,6]])
	print('x size :',x.size)
	#输出内容:x size : 5
	print('y size :',y.size)
	#输出内容:y size : 6

dtype 元素类型

    x=np.array([1,2,3,4,5])
	y=np.array([[1,2,3],[4,5,6]])
	print('x dtype :',x.dtype)
	#输出内容:x dtype : int64
	print('y dtype :',y.dtype)
	#输出内容:y dtype : int64

矩阵的合并

在numpy中矩阵的合并主要采用如下的方法

    a=np.array([[1,2],[3,4]])
	b=np.array([[5,6],[7,8]])
	c=np.hstack((a,b)) #矩阵的横向合并
	print(c)
	#输出内容
	#[[1 2 5 6]
    # [3 4 7 8]]
	d=np.vstack((a,b)) #矩阵的纵向合并
	print(d)
	#输出内容
    #[[1 2]
    # [3 4]
    # [5 6]
    # [7 8]]
    e=np.concatenate((a,b),axis=0) #矩阵的横向合并
	print(e)
	#输出内容
    #[[1 2]
    # [3 4]
    # [5 6]
    # [7 8]]
	f=np.concatenate((a,b),axis=1) #矩阵的纵向合并
	print(f)
	#输出内容
	#[[1 2 5 6]
    # [3 4 7 8]]

note:矩阵的合并有比较大的条件限制,矩阵合并首先要保证合并矩阵的维度必须是一致的,而且形状也需要符合合并的要求。

矩阵的切分

numpy对于矩阵的切分主要有如下几个方式。

    a = np.arange(0, 12).reshape((3, 4))
    print(a)
    #输出内容为:
    #[[ 0  1  2  3]
    # [ 4  5  6  7]
    # [ 8  9 10 11]]
    b=np.hsplit(a,2) #行切分矩阵
    #输出内容为:
    #[array([[0, 1],
    #        [4, 5],
    #        [8, 9]]), 
    #  array([[ 2,  3],
    #         [ 6,  7],
    #         [10, 11]])]
    print(b)
    c=np.vsplit(a,1) #列切分矩阵
    print(c)
    #输出内容:
    #[array([[ 0,  1,  2,  3],
    #        [ 4,  5,  6,  7],
    #        [ 8,  9, 10, 11]])]
    d=np.split(a,2,axis=1) #axis=1 表示行切分矩阵,axis=0 表示列切分矩阵,平均切分。如果不能平局切分会报错
    print(d)
    #输出内容:
    #[array([[0, 1],
    #        [4, 5],
    #        [8, 9]]), 
    # array([[ 2,  3],
    #        [ 6,  7],
    #        [10, 11]])]
    d=np.array_split(a,3,axis=1) #axis=1 表示行切分矩阵,axis=0 表示列切分矩阵。与split不同的是可以平均切分
    print(d)
    #输出内容:
    #[array([[0, 1],
    #        [4, 5],
    #        [8, 9]]),
    # array([[ 2],
    #        [ 6],
    #        [10]]), 
    # array([[ 3],
    #        [ 7],
    #        [11]])]

矩阵的深拷贝和浅拷贝

在使用numpy我们常常会遇到如下的场景

    a=np.arange(0,8).reshape(4,2)
    print(a)
    #输出内容:
    #[[0 1]
    # [2 3]
    # [4 5]
    # [6 7]]
    b=a[2,:]
    b[0]=11
    print(a)
    #输出内容:
    #[[0 1]
    # [2 3]
    # [11 5]
    # [6 7]]

发现我们修改了b的值,但是a随之改变。这里我们可以这里数据关联看作C中指针,改变一个数据本质上另一个数据也随之发生改变。 如果解决这个问题,可以采用深拷贝的知识,具体实现如下

    a=np.arange(0,8).reshape(4,2)
    print(a)
    #输出内容:
    #[[0 1]
    # [2 3]
    # [4 5]
    # [6 7]]
    b=np.copy(a)[2,:]
    b[0]=11
    print(a)
    #输出内容:
    #[[0 1]
    # [2 3]
    # [4 5]
    # [6 7]]

采用np.copy方法对a进行深拷贝,那么修改b的值,a就不会随之变化。