Numpy
NumPy(Numerical Python)是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
numpy是一个用python实现的科学计算,包括:
1、一个强大的N维数组对象Array;
2、比较成熟的(广播)函数库;
3、用于整合C/C++和Fortran代码的工具包;
4、实用的线性代数、傅里叶变换和随机数生成函数。numpy和稀疏矩阵运算包scipy配合使用更加方便。
NumPy(Numeric Python)提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。
Numpy属性
定义一个array,其中的长宽、维数等等都是numpy的属性。
import numpy as np
array = np.array( [[1,2,3],
[3,4,5]] )
print(array)
以上就是一个简单创建和输出array的代码
print('number of dim:',array.ndim)#输出矩阵的维数
print('shape:',array.shape)#输出矩阵的行数和列数
print('size',array.size)#输出矩阵元素个数
通过array的内置函数,可以输出矩阵的维数,矩阵的行列数以及矩阵元素的个数等等。这些都是矩阵的基本属性。需要提醒的是,shape输出结果,第一位元素代表行数,第二位元素代表列数。
Numpy数据类型
numpy中可以创建各种各样的矩阵和数组。在创建array时,可以定义这个矩阵的数据类型(type)。那numpy有哪些数据类型?
名称 | 描述 |
---|---|
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64 |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 np.bool_,np.int32,np.float32,等等。
a=np.array([1,2,3],dtype=np.int)
print(a.dtype)#输出a的数据类型
#int默认是64位整型
通常位数更小,所占内存就越小,但运算速度就会越慢。
Numpy创建array
numpy中生成数组的方法有很多:
- 生成一个空的数组(其实是一个几乎为0的数组):empty(shape[, dtype, order])
a = np.empty((3,4))#参数需要是元组形式
- 生成一个所有元素全为0的数组(np.zeros((行数,列数))):zeros(shape[, dtype, order])
b = np.zeros((3,4))
- 生成一个所有元素都为1的数组:ones(shape[, dtype, order])
c = np.ones((3,4),dtype=np.int16)
#可以直接在后面对数组元素的数据类型进行定义
- 生成有序的序列或矩阵,需要起始值和终止值
d = np.arange(10,20,2)#起始为10,终止为20,步长为2的元素组成的序列
如果想要获得一个矩阵,就需要重写序列的shape:
d = np.arange(12).reshape((3,4))
- 生成线段,比如说从最开始的数值1到10,最后一个给定参数是需要在这个区间需要多少段。第一个参数是起始值,第二个参数是终止值,第三个参数是我们需要多少这样的线段,他会根据需要的线段数量来自动确定步长。
e = np.linspace(1,10,20)#起始值是1,终止值是10,要获得20条线段
当然,生成线段,也可以更改数组的shape。
除此之外,numpy还有很多生成数组的方法:
- empty(shape[, dtype, order])
- empty_like(a[, dtype, order, subok])
- eye(N[, M, k, dtype, order])
- identity(n[, dtype])
- ones(shape[, dtype, order])
- ones_like(a[, dtype, order, subok])
- zeros(shape[, dtype, order])
- zeros_like(a[, dtype, order, subok])
- full(shape, fill_value[, dtype, order])
- full_like(a, fill_value[, dtype, order, subok])
Numpy基础运算
1.array减法
a = np.array([10,20,30,40])
b = np.arange(4)
print(a,b)
c = a - b#array减法
print(c)
2.array加法
a = np.array([10,20,30,40])
b = np.arange(4)
print(a,b)
c = a + b#array加法
print(c)
3.array乘法(都是相似的)
b = np.arange(4)
c = b**2#b数组的平方:每个元素分别平方,组成c
print(c)
4.求三角函数,需要调用numpy中的内置函数
a = np.array([10,20,30,40])
c = 10*np.sin(a)#求余弦
print(c)
5.判断array中有多少个元素大(小)于指定元素,即比较大小
b = np.arange(4)
print(b)
print(b<3)#布尔型返回True or False
#运行结果:
#[0 1 2 3]
#[ True True True False]
6.矩阵运算
numpy中乘法分两种,一个是逐个相乘,一个是矩阵乘法。逐个相乘:c=a*b,和矩阵乘法,需要调用numpy中的dot()函数。
a = np.array([[1,1],
[0,1]])
b = np.arange(4).reshape((2,2))
print('a:',a)
print('b:',b)
c = a*b#矩阵元素逐个相乘
c_dot = np.dot(a,b)
c_dot_2 = a.dot(b)#矩阵乘法的两种表达形式
print('c:',c)
print('dot1:',c_dot)
print('dot2:',c_dot_2)
7.在随机生成的array中最大/小值,以及求和
a = np.random.random((2,4))#后一个random就是reshape的作用
print(a)
print(np.sum(a))#求和
print(np.min(a))#求最小值
print(np.max(a))#求最大值
8.最大/最小值索引;平均值;中位数
a = np.arange(2,14).reshape((3,4))
print(a)
print(np.argmin(a))#计算最小值的索引(是下标)
print(np.argmax(a))#计算最大值的索引
print(np.mean(a))
print(a.mean())#计算矩阵的平均值(两种形式)
print(np.median(a))#计算中位数
9.矩阵逐步累加
a = np.arange(2,14).reshape((3,4))
print(a)
print(np.cumsum(a))#每一位都是前位元素累加而成
10.矩阵逐步累差
矩阵逐步累差的过程,原矩阵本来是3行4列,累差以后是3行3列的矩阵。因为四个数,每两个数相差的话,只会输出三个值。
a = np.arange(2,14).reshape((3,4))
print(a)
print(np.diff(a))
11.找出非0数
使用nonzero输出的是两组array,一组表示非0元素所在行数,一组表示非0元素所在列数。
a = np.arange(2,14).reshape((3,4))
print(a)
print(np.nonzero(a))
12.矩阵排序
矩阵排序需要定义步长,并且排序是逐行进行的。
a = np.arange(14,2,-1).reshape((3,4))
print(a)
print(np.sort(a))#分别对每行进行排序
'''
运行结果:
原矩阵: [[14 13 12 11]
[10 9 8 7]
[ 6 5 4 3]]
排序后: [[11 12 13 14]
[ 7 8 9 10]
[ 3 4 5 6]]
'''
13.矩阵相乘
numpy中计算矩阵相乘,需要先计算矩阵的转置。
a = np.arange(14,2,-1).reshape((3,4))
print('原矩阵',a)
print('a的转置:',np.transpose(a))
print('a的转置:',a.T)#求矩阵的转置
print('矩阵乘法:',(a.T).dot(a))#矩阵乘法(a的转置乘以a)
14.clip函数
numpy.clip(a, a_min, a_max, out=None);其实就是把数组a的元素限制到[a_min, a_max]区间内。
给定最小值和最大值,这个array中所有小于最小值的元素,都让他们等于最小值;所有大于最大值的元素,都让他们等于最大值,中间元素不变。
a = np.arange(14,2,-1).reshape((3,4))
print(a)
print(np.clip(a,5,9))#限制元素值域,最小值为5,最大值为9
注意:
- numpy的所有指令都可以指定需要对行计算还是对列计算(axis=‘ ’,0对行操作,纵向的操作,1对列操作,横向的操作)
- numpy中还有其他运算,这里没有全部罗列
Numpy的索引
如何在numpy中根据他的位置找到他的值?
1.在一维array中,元素的下标就是其索引。
a = np.arange(3,15)
print(a)
在二维的array中,
a = np.arange(3,15).reshape((3,4))
print(a)
print(a[2])#输出是一行数据,不是单个数据
想要输出指定的某个元素,需要指定他的位置(行和列)。
print(a[2][1])
print(a[2,1])#两种通过索引指定元素的表达方式
也可以用冒号来表示某一行的所有数A[2,:],或者某一列的所有数A[:,1]
print(a[1,1:2])
#表示第一列从位置1到位置2的值(不包含结尾位置)
2.可以通过for循环来输出每行元素。
a = np.arange(3,15).reshape((3,4))
print(a)
for row in a:
print(row)#输出的数矩阵中的每一行
在numpy中没有遍历输出每一列的操作,通过转置来迭代转置矩阵的行,其实就是原来矩阵的列。
for column in a.T:
print(column)
3.如果想要通过迭代来print出他的项目应怎么做呢?如果直接在a中去遍历,迭代的是a中的行;要想迭代项目,需要先将array的格式进行转变。
print(a.flatten())#flatten()一个函数,返回了一个被改变的array
for item in a.flat:#flat是一个迭代器
print(item)#输出的是array中的一个一个元素
Numpy的array合并
array的合并要分为按行或列合并
1.两个array上下合并
a = np.array([1,1,1])
b = np.array([2,2,2])
print(np.vstack((a,b)))#vertical stack,对两个array上下进行合并
#vstack()函数的参数是元组形式
两个array进行上下合并后,就称为一个矩阵。
a = np.array([1,1,1])
b = np.array([2,2,2])
c = np.vstack((a,b))
print(a.shape,c.shape)#输出a和c的结构
'''
运行结果:
(3,) (2, 3)
由此可知,a是一个一维序列,c是2行3列的二维序列
'''
2.两个array左右合并
d = np.hstack((a,b))#horizontal stack
print(d)
print(a.shape,d.shape)
'''
运行结果:
[1 1 1 2 2 2]
(3,) (6,)
由此可知,a,b两个序列左右合并后得到的是还是一个一维的序列
'''
但需要注意的是,我们不能通过transpose这个方法去改变序列的方向(即,不能将横向的序列改变成竖向的序列),这个方法只适用于矩阵。那么如何实现将一个横向的数列变成竖向的数列呢?需要调用numpy的newaxis方法[np.newaxis,:]
,对araay新加一个维度(冒号在后,是多加了一个行的维度;冒号在前,是多加了一个列的维度)。
a = np.array([1,1,1])[:,np.newaxis]
b = np.array([2,2,2])[:,np.newaxis]#冒号在前就是多加了一个列的维度
d = np.hstack((a,b))#horizontal stack
print(d)
print(a.shape,d.shape)
'''
运行结果:
[[1 2]
[1 2]
[1 2]]
(3, 1) (3, 2)
由此可知,在经过newaxis方法后,a,b两个序列都增加了一个列的维度,在左右合并了以后就成为了一个3行2列矩阵,相当于a,b两个序列转置后,再合并。
'''
3.多个array纵向或横向的合并
a = np.array([1,1,1])[:,np.newaxis]
b = np.array([2,2,2])[:,np.newaxis]#冒号在前就是多加了一个列的维度
print(np.hstack((a,a,b)))#多个array进行左右合并
c = np.concatenate((a,b,b,a))
#concatenate可以设置在哪一个维度进行合并,默认axis=0,上下合并
print(c)
concatenate方法中,设置axis=1,左右合并。
c = np.concatenate((a,b,b,a),axis=1)
'''
运行结果:
[[1 2 2 1]
[1 2 2 1]
[1 2 2 1]]
'''
Numpy的array分割
1.将array分割成不同的片段(也分横向/纵向的分割),要用到numpy中的split方法,其中第一个参数为目标array,第二个参数为分割数目,第三个参数axis设置分割方向。
a = np.arange(12).reshape((3,4))
print(a)
print(np.split(a,2,axis=1))#a这个序列,分割成2个片段,按照列分割(左右分割)
'''
运行结果:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[array([[0, 1],
[4, 5],
[8, 9]]), array([[ 2, 3],
[ 6, 7],
[10, 11]])]
'''
需要注意的是,上述示例可以对行进行分割分成3个片段,因为有3行。但是不可以对列进行分割成3个片段,因为array只能进行相等的分割,4列不可以分成3份。
2.那如何实现不等量的分割呢?在numpy中进行不等量的分割:
print(a)
print(np.array_split(a,3,axis=1))
'''
运行结果:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[array([[0, 1],
[4, 5],
[8, 9]]), array([[ 2],
[ 6],
[10]]), array([[ 3],
[ 7],
[11]])]
由此可见,在对array进行不等量分割时,首先将前两列分为一块,第三列为一块,最后一列为一块
'''
3.分割函数
- 纵向的分割(对行操作)
print(np.vsplit(a,3))
'''
运行结果:
[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]
'''
- 横向的分割(对列操作)
print(np.hsplit(a,2))
'''
运行结果:
[array([[0, 1],
[4, 5],
[8, 9]]), array([[ 2, 3],
[ 6, 7],
[10, 11]])]
'''
Numpy的copy和deep copy
在对numpy进行赋值时,值具有传递性。
a = np.arange(4)
print(a)
b = a
c = a
d = b
a[0] = 11#改变a中的元素,同时也改变了b中的元素
print(b is a)
#因为前面a=b=c=d,因此改变其中任意个array中的元素,其他array也会发生变化
d[1:3] = [22,33]#对d中第2/3个元素进行修改,a中元素也会修改
print('d:',d)
print('a:',a)
'''
运行结果:
[0 1 2 3]
True
d: [11 22 33 3]
a: [11 22 33 3]
'''
如果想要a的值,但是不想要关联a序列,就需要用到copy函数:
a = np.arange(4)
print(a)
b = a.copy()#deep copy,只获得a中的值,但没有关联a
print(b)
a[3] = 44#修改a中元素
print('a:',a)
print('b:',b)#不会跟随a的修改而修改其中的元素
'''
运行结果:
[0 1 2 3]
[0 1 2 3]
a: [ 0 1 2 44]
b: [0 1 2 3]
'''