简介
numpy是python的一个开源的数值计算库,该库可以用来存储和处理大型矩阵,比python的自带的list和tuple处理效率更高。
numpy的创建和引入
numpy是python的一个开源库,安装好python后可以采用如下的方式,安装numpy。
pip3 install numpy
代码中引入numpy也很简单,采用如下方式就可以了。
import numpy as np
矩阵的创建
常规的方法:
- 一维矩阵
array1=np.array([1,2,3,4,5])
- 二维矩阵
array1=np.array([[1,2,3,4,5],[2,3,4,5,6]])
- 三维矩阵
array1=np.array([[[1,2,3,4,5],[2,3,4,5,6]]])
可以看出创建什么样可以将相关矩阵直接传入就可以了。
快捷的方法是
- 创建全0矩阵,其中(2,3)表示生成的是2行,3列的矩阵
x=np.zeros((2,3))
print(x)
#输出内容
#[[0,0,0]
# [0,0,0]]
- 创建全1矩阵,其中(2,3)表示生成的是2行,3列的矩阵
x=np.ones((2,3))
print(x)
#输出内容
#[[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]]
- 创建单元矩阵,其中2表示的是2*2的矩阵
x=np.eye(2)
print(x)
#输出内容
#[[ 1. 0.]
# [ 0. 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]]
- 创建指定形状的随机矩阵
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就不会随之变化。