Python:numpy
学习自:NumPy 教程 | 菜鸟教程
官网:Numpy官方文档
1、简介
numpy主要用于数组计算,包含:
1)一个强大的N维数组对象ndarray
2)广播功能函数
3)整合 C/C++/Fortran代码的工具
4)线性代数、傅里叶变换、随机数生成等功能
numpy通常与scipy(scientific Python)和matplotlib(绘图库)一起使用,这种组合广泛用于替代MatLab,是一个强大的科学计算环境,有助于我们通过Python学习数据科学或者机器学习。
scipy是一个开源的Python算法库和数学工具包。
scipy中包含的模块有最优化、线性代数、积分、插值、特殊函数、快速傅里叶变换、信号处理和图像处理、常微分方程求解、....
matplotlib是Python编程语言及numpy库的可视化操作界面。它为通用的图形用户界面(GUI)提供了应用程序接口(API),常用的GUI工具包有Tkinter,wxPython,Qt、GTK+。
2、Ndarray对象
numpy最重要的特点是Ndarray对象,Ndarray对象即N维数组对象,它是一系列同类型数据的集合,以0为下标开始进行集合中元素的索引。
特性
1)元素为同类型
2)每个元素在内存中占用空间相同
创建一个ndarray只需要调用numpy.array()即可
numpy.array( object, dtype=None, copy=True, order=None, subok=False, ndmin=0 )
参数
参数 | 说明 |
object | 数组或嵌套的List |
dtype | 数组元素的数据类型 |
copy | 对象是否需要复制 |
order | 创建数组的方向,C为行方向,F为列方向,A为任意方向(默认) |
subok | 默认返回一个与基类类型一致的数组 |
ndmin | 指定生成数组的最小维度 |
创建时指定dtype和ndmin,可以补充更多细节,举例如下:
nd = np.array( [1,2,3], ndmin=2 #最小维度为2 ) [[1 2 3]] nd = np.array( [1,2,3], dtype=complex #指定类型为负数 ) [1.+0.j 2.+0.j 3.+0.j]
补充
1)二维数组生成时,各行间以逗号,隔开,每个list代表一行
2)n维数组就是n个[]的嵌套
3)生成类似
[("raju",21),("anil",25),("ravi", 17), ("amar",27)]
的数组时,dtype需要为每个字段指定名称和类型,方式为:
dt = np.dtype( [ (name1 , dtype) , (name2 , dtype) , ... ] )
而上述数组的生成则为
dt = np.dtype([('name', 'S10'),('age', int)]) a = np.array([("raju",21),("anil",25),("ravi", 17), ("amar",27)], dtype = dt)
2.1、属性
ndarray.属性名
属性 | 说明 |
ndim | 维数 |
shape | 尺寸,返回(n,m)说明是n行m列 |
size | 元素个数,等于n*m |
dtype | 元素类型 |
itemsize | 每个元素大小,以字节B为单位 |
flags | 内存 |
real | 元素实部 |
imag | 元素虚部 |
numpy提供了reshape()函数来调整数组的大小
用法
a = np.array([[1,2,3],[4,5,6]]) b = a.reshape(3,2) #把数组a素重新组合为3行2列的新数组 print (b) [[1 2] [3 4] [5 6]]
reshape返回原数组的变形后的副本,因此对新数组b中元素值的改写,会导致a中对应值的变化。
如果传入参数-1,那么会返回原数组对应的一维向量,长度为n*m。
3、创建数组
3.1、array
见上文
3.2、直接创建
除了用array方法构造一个数组外,也可以通过以下几种方式创建:
3.2.1、empty
说明
empty方法创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
用法
numpy.empty( shape, dtype=float, order='C' )
参数
参数 | 说明 |
shape | 形状;形式为[n,m]或(n,m),n行m列 |
dtype | 类型 |
order | 顺序;'C'或'F'分别表示行优先和列优先 |
3.2.2、zeros
说明
创建指定大小的数组,元素填充0
用法
numpy.zeros( shape, dtype=float, order='C' )
参数同empty
3.2.3、ones
说明
创建指定大小的数组,元素填充1
用法
numpy.ones( shape, dtype=None, order='C' )
3.3、利用random库生成随机数组——np.random模块
学习自:numpy的random模块详细解析 - 左手十字 - 博客园
Random sampling (numpy.random) — NumPy v1.21 Manual
以下在使用时,都要先用import random.randxxx导入相关的库
函数 | 说明 |
rand(x,y,z) | 生成0-1间的随机值矩阵,尺寸为x*y*z |
randn(x,y,z) | [-1,1]标准正态分布矩阵,尺寸为x*y*z |
randint(low,high,size) | [low,high)区间内尺寸为size的随机整数,size=(3,3)表示3*3的矩阵 |
random(size) | 返回在区间[0,1)内的浮点数,尺寸为size |
以上生成随机数的方法,有可能出现重复的情况,如果要避免这种情况,可以用random.sample( a , n )(注意,这里是random模块而非np.random)
random.sample( a,n )可以在一个序列a中不重复地采样n个值。
3.4、从已有的数组创建数组
3.4.1、asarray
说明
生成list、tuple等元素组的数组形式
用法
numpy.asarray( a, dtype = None, order = None )
参数
a:任意形式的输入参数,可以是:list、tuple,互相嵌套的list和tuple、多维数组
例子
a=numpy.asarray([(1,2,3),(4,5)])
a
array([(1, 2, 3), (4, 5)], dtype=object)
3.4.2、fromiter
说明
从可迭代对象中建立ndarray对象,返回一维数组
用法
numpy.fromiter( iterable, dtype, count=-1 )
参数
参数 | 说明 |
iterable | 可迭代对象 |
dtype | 返回数组的数据类型,必需 |
count | 读取的数量,默认-1即全部 |
例子
list=range(5) x=numpy.fromiter(list, dtype=float) x array([0., 1., 2., 3., 4.]) x=numpy.fromiter(list, dtype=float,count=3) #只读取3个 x array([0., 1., 2.])
3.5、从数值范围创建数组:arange、linspace、logspace
3.5.1、arange
说明
根据范围和步长,返回一个一位数组
用法
numpy.arange(
start = 0,
stop,
step = 1,
dtype = None
)
参数
参数 | 说明 |
start | 起始值,默认0 |
stop | 终止值(不包含) |
step | 步长,默认1 |
dtype | 类型,默认使用输入数据的类型 |
例子
x=np.arange(5) #0到4 x array([0, 1, 2, 3, 4]) x=np.arange(10,20)#10到19 x array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
3.5.2、linspace
说明
根据范围和数组中元素数量,返回一个等差数列一维数组
区别于arange:arange是给出了步长,元素数量由步长决定;linspace是给出了数量,步长由数量决定
用法
numpy.linspace( start, stop, num=50, retstep=False, dtype=None )
参数
参数 | 说明 |
start | 起始值 |
stop | 终止值(包含) |
num | 元素数量 |
retstep | 如果为True,则生成的数组中会显示间距,反之不会 |
dtype | 类型 |
例子
只看retstep的效果
x=np.linspace(10,20,11,retstep=True)
x
(array([10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20.]), 1.0)
3.5.3、logspace
说明
创建一个指定元素个数等比数列一位数组
用法
np.logspace( start, stop, num=50, endpoint=True, base=10.0, dtype=None )
参数
参数 | 说明 |
start | 序列的起始值为:base**start(即base^start) |
stop | 序列的终止值为:base**stop(包含) |
num | 元素数量 |
base | 底数,用于生成起始值和终止值 |
dtype | 类型 |
补充
当start-stop+1 == num时,会生成从base**start 到 base**stop的等比数列,比值为base,数量为num
例子
生成1,2,4,8,...,512
#1=2**0 512=2**9 所以start=0,end=9,num=9-0+1=10 x=np.logspace(0,9,10,base=2) x array([ 1., 2., 4., 8., 16., 32., 64., 128., 256., 512.])
4、切片与索引
4.1、切片
4.1.1、一维数组
通过 [start:stop:step]来进行切片操作,stop不包含其中
a=np.arange(10) b=a[2:7:2] b array([2, 4, 6])
另外,还有其他几种写法
[start :] | 从start到最后(步长为1) |
[: stop] | 从开始到stop(不包含) |
[start : : step]与[: stop : step] | 前两种的延伸,指定步长 |
4.1.2、二维数组
[r_start:r_stop , c_start:c_stop]
写法与一维数组相同,不过格式要多一个维度
例子
a=np.arange(20) c=a.reshape(5,4) array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]) #c是5行4列的数组
#下面提取2、3行,1、2列的元素 c[1:3,0:2] array([[4, 5], [8, 9]])
4.1.3、用省略号...全选某一列/行
在处理多维数组时,如果某若干行/列的元素时,可以用以下两种方式
#提取第3列 c[:,2] array([ 2, 6, 10, 14, 18]) c[...,2] array([ 2, 6, 10, 14, 18]) #提取第3行 c[2,:] array([ 8, 9, 10, 11]) c[2,...] array([ 8, 9, 10, 11])
个人还是更习惯用冒号:
4.2、高级索引
4.2.1、数组形式的索引
用法(以二维数组为例):
#x为一二维数组 x[ [x1,x2] , [y1,y2] ]
上述索引的结果为一个一维数组[ x[x1,y1] , x[x2,y2] ],行索引与列索引中的元素一一对应,两两组合得到实际的索引。
4.2.2、布尔索引(很有用)
说明:筛选获得符合指定条件的数组元素
要求:索引必须返回布尔值(True或False)
用法:
x[ x > 5 ] | 筛选x中大于5的元素 |
x[ func (x) ] | 筛选x中符合函数func的元素,要求func必须返回True或False |
例子:
#逻辑运算 a=np.array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]) a[a > 5] array([ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]) #函数 b = np.array([1, 2+6j, 5, 3.5+5j]) b[np.iscomplex(b)] array([2. +6.j, 3.5+5.j])
如果想看数组元素对于布尔运算的实际响应,可以直接用 索引
a > 5
array([[False, False, False, False],
[False, False, True, True],
[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True]])
np.iscomplex(b)
array([False, True, False, True])
4.2.3、花式索引
说明:以任意顺序取整行和整列构成新数组
区别于整数数组索引:
整数数组索引总是同时给出相同尺寸的行list和列list,从而获取某个具体元素的下标(下标获取方式为,同一个位置的行对应同一个位置的列,对应关系为一对一;假设list尺寸为n,则最终提取n个元素);
花式索引:
给出一个list时,标识具体的行,提取整行元素作为一个新的数组;
给出两个list时(需要用到np.ix_方法),行下标list与列下标list的对应关系为一对多,每个行下标都会与每个列下标互相组合,此时行list与列list尺寸可以不同,假设行列list尺寸分别为m与n,那么最终提取m*n个元素,即m行n列
例子:
①传入一个list
a=np.arange(20) c=a.reshape(5,4)#c为5*4的数组
#第3行 c[2] array([ 8, 9, 10, 11]) #第4、1、2、3行 c[ [3,0,1,2] ] array([[12, 13, 14, 15], [ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
②传入两个list
c[ np.ix_( [3,0,1,2] , [2,0,1] ) ] #行组织方式为原数组的3、0、1、2行 #列组织方式为原数组的对应行2、0、1列
#综合起来就是
#3行2列 3行0列 3行1列
#0行2列 0行0列 0行1列
#... array([[14, 12, 13], [ 2, 0, 1], [ 6, 4, 5], [10, 8, 9]])
5、数组操作
分类:修改数组形状、转置、连接、分割、去除重复
之所以这一节的标题用数组操作而不是方法,是因为有些操作是方法,有些是属性
5.1、修改数组形状
reshape | 不改变数据的条件下修改形状 |
flatten | 返回展开数组的拷贝,对拷贝的修改不会影响原始数组 |
ravel | 返回展开数组,修改会影响原始数组 |
flat(属性) | 数组元素迭代器 |
meshgrid | 1D数组网格化为2D网格 |
5.1.1、reshape
用法:
nd.reshape(m,n)
说明:将a重构为m*n大小,返回重构后的数组,前提是m*n == a.size()
5.1.2、flatten
用法:
nd.flatten(order = 'C')
参数:
order:展开方式,'C'——按行、'F'——按列
说明:按参数order说明的方式将数组展开,返回展开数组的拷贝,对拷贝的修改不影响原始数组
5.1.3、ravel
用法:
nd.ravel(order = 'C')
参数和说明都与flatten相同,不同之处在于没有拷贝,修改会影响原始数组
5.1.4、flat(属性)
nd.flat
说明:返回一个iterable,可以用for循环迭代访问全部数组元素
迭代访问数组元素的方法:
#1. a.flat for element in a.flat : print(element) #2. a.ravel()和a.flatten() for element in a.ravel(): print(element) for element in a.flatten(): print(element) #3. a.shape for i in range(a.shape[0]): for j in range(a.shape[1]): print(a[i,j]) #如果直接对数组迭代,返回的只是各行,可通过对这些行二次迭代实现访问所有元素的目的 #4. for row in a: for element in row: print(element)
推荐使用1、3、4种,当然一维数组直接用一个for循环就可以了
5.1.5、meshgrid
说明
由低维数组生成高维网格,主要用于生成坐标系的各个轴坐标(区域插值、等高线绘制常用)。
如果参数中有n个xi,那么最终生成的就是n维网格。
不过我们最常用的是两个xi,即x和y,这样生成的就是二维坐标系的横纵坐标。
这些xi都是1D array,尺寸可以不同,最终生成的坐标系大小就是len(x1)*len(x2)*len(x3)*...
用法
np.meshgrid(x1,x2,...,xn, copy=True, sparse=False, indexing='xy')
参数
参数 |
类型 |
默认值 |
说明 |
x1,x2,...,xn | 1D array | 用于构建坐标网格的各个轴,最终的坐标系大小就是这些轴的乘积 | |
indexing | {'xy','ij'} | 'xy' |
输出的坐标系 'xy':笛卡尔坐标系 ''ij':矩阵坐标系 |
sparse | bool | False | 是否返回稀疏矩阵以节约内存 |
copy | bool | True |
如果是True,会新生成结果array; False,则是在原array上生成,以节约内存。 |
返回值
与输入的x1、x2、...、xn个数相等的X1、X2、...、Xn,它们都是n维数组。
假设x1~xn的大小为Ni=len(xi),那么,根据参数indexing的取值,X1~Xn有不同的取值:
- 'ij':X1~Xn为(N1,N2,N3,...,Nn)尺寸的array
- 'xy':X1~Xn为(N2,N1,N3,...,Nn)尺寸的array
有n个xi,结果就要用n个Xi承接:
X1,X2,...,XN = np.meshgrid(x1,x2,...,xn)
例子
①
import numpy as np nx,ny=(3,2) x=np.linspace(0,1,nx)#(0,1)间生成3个点 y=np.linspace(0,1,ny)#(0,1)间生成2个点 xv,yv=np.meshgrid(x,y) print(xv,yv) [[0. 0.5 1. ] [0. 0.5 1. ]] [[0. 0. 0.] [1. 1. 1.]] xv, yv = np.meshgrid(x, y, sparse=True)#稀疏矩阵 print(xv,yv) [[0. 0.5 1. ]] [[0.] [1.]]
②坐标系绘图
import matplotlib.pyplot as plt x = np.arange(-5, 5, 0.1) y = np.arange(-5, 5, 0.1) xx, yy = np.meshgrid(x, y, sparse=True) z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2) h = plt.contourf(x, y, z) #等值区域图 plt.axis('scaled') plt.show()
5.2、转置
两种实现途径:numpy.transpose()、ndarray.T
a.T array([[1, 2], [2, 3], [3, 4]]) np.transpose(a) array([[1, 2], [2, 3], [3, 4]])
5.3、连接数组:concatenate
用法:
np.concatenate((a1,a2,...),axis=0)
参数:
a1,a2,...:相同类型的数组
axis:连接数组的方向(默认0,即行方向)
说明:axis为0,将a2按行的方式成为a1的新行加入到a1中;axis为1,按列加入
a=np.arange(1,5).reshape(2,2) b=np.arange(5,9).reshape(2,2) np.concatenate((a,b)) #行拼接 array([[1, 2], [3, 4], [5, 6], [7, 8]]) np.concatenate((a,b),1) #列拼接 array([[1, 2, 5, 6], [3, 4, 7, 8]])
5.4、分割数组:np.split
用法:
np.split(
arr,
indices_or_sections,
axis
)
参数:
arr:被分割的数组
indices_or_sections:如果是一个整数n,则平均切分为n份;如果为list,则切点位置为list中的数字(切点元素归下一个数组,即1号切点元素在第2个数组中,2号切点在第3个数组中)
axis:切割方向;默认0,对行切割,新数组列数同原数组;axis=1,对列切割,新数组行数同原数组
5.5、去除重复元素:unique
说明:去除数组中的重复元素,返回一个全是不同元素的一位数组
用法:
np.unique(
arr,
return_index,
return_inverse,
return_counts
)
参数:
arr:输入数组,如果不是一位数组则会展开
return_index:如果为True,返回去重数组中的元素在旧list中的下标,以一维数组形式存储
return_inverse:如果为True,返回去重数组中的元素在新list中的下标,以一维数组形式存储
return_counts:如果为True,返回去重数组中的元素在原数组中的出现次数,以一维数组形式存储
例子:
u,index,indice,c=np.unique(a,return_index=True,return_inverse=True,return_counts=True) u #去重数组 array([2, 5, 6, 7, 8, 9]) index #元素在旧数组中的下标 array([1, 0, 2, 5, 8, 4], dtype=int64) indice #元素在新数组中的下标 array([1, 0, 2, 0, 5, 3, 1, 2, 4, 0], dtype=int64) c #各元素出现次数 array([3, 2, 2, 1, 1, 1], dtype=int64)
6、取整
取整操作返回取整后的数组,对原数组没有影响
6.1、四舍五入:np.around
说明:对整个数组的所有元素进行四舍五入
用法:
np.around(a , decimals=0)
参数:
a:数字数组
decimals:保留到哪一小数位。默认为0,即个位;1表示小数点后1位,-1表示十位,-2表示百位
6.2、向下取整:np.floor
说明:数值上小于或等于原数的最大整数,而非绝对值
用法:np.floor(a)
6.3、向上取整:np.ceil
说明:数值上大于或等于原数的最小整数
用法:np.ceil(a)
7、算数函数
7.1、倒数:np.reciprocal()
说明:返回逐元素取倒数后的新数组
用法:np.reciprocal(a)
8、统计函数
8.1、最大、最小值:np.amin()与np.amax()
用法:
二者用法相同,以amax说明
np.amax(a ,axis = None)
参数:
a:数组
axis:方向;默认None是全数组,0是列方向——给出每列最大值的array,1是行方向——给出包含每行最大值的array
8.1.5、最大最小值的索引:np.argmax()与np.argmin()
用法:
np.argmax(a ,axis = None)
参数同上
说明:argmax返回amax选出的最大值在原数组中的索引;即形式与amax相同,但数值是这些数的索引
8.2、最大最小元素之差:np.ptp()
用法:
np.ptp(a , axis = None)
参数:
a:数组
axis:方向,默认None是全数组,0是列方向——给出每列最大值的array,1是行方向——给出包含每行最大值的array
8.3、中位数:np.median()
用法:
np.median(a , axis = None)
参数同上
8.4、算数平均值:np.mean()
用法:
np.mean(a , axis = None)
参数同上
8.5、加权平均值:np.average()
说明:该函数根据在另一个数组中给出各自的权重计算给定数组中各元素的加权平均值
用法:
np.average( arr, axis=None, weights, returned=False )
参数:
arr:原数组
axis:方向,同上
weights:权重数组;如果axis=None,那么尺寸与arr相同,是对每个元素的加权;如果axis=0,尺寸等于行数,是每列元素的加权平均值;如果axis=1,尺寸等于列数,是每行元素的加权
returned:如果为True,则额外返回权重的和
8.6、标准差:np.std()
用法:
np.std(a , axis=None)
8.7、方差:np.var()
用法:
np.var(a , axis=None)
9、排序、按条件筛选元素
9.1、排序
9.1.1、元素排序:np.sort()
用法:
numpy.sort(
a,
axis = -1,
kind = 'quicksort',
order = None
)
参数:
a:待排序数组
axis:方向;axis = 0 ,按列进行排序;axis = 1,按行进行排序。默认为-1,即最大的axis,二维情况下为1,三维情况下为2
kind:排序算法,默认为快速排序
order:如果数组包含字段,则该参数指定参与排序的字段
例子:
#axis a = np.array([[3,7],[9,1]]) np.sort(a) #行排序 array([[3, 7], [1, 9]]) np.sort(a,axis=0) #列排序 array([[3, 1], [9, 7]]) #order dt = np.dtype([('name', 'S10'),('age', int)]) a = np.array([("raju",21),("anil",25),("ravi", 17), ("amar",27)], dtype = dt) #按name排序 np.sort(a, order = 'name') [(b'amar', 27) (b'anil', 25) (b'raju', 21) (b'ravi', 17)]
9.1.2、排序后的索引值:np.argsort()
用法:
np.argsort( a, axis = -1, kind = 'quicksort', order = None )
说明:返回对数组a进行np.sort排序后,排序结果在原数组中的索引下标
9.2、筛选
其实在4.2布尔索引已经讲了如何筛选数组中符合条件的元素,这里给出获取筛选元素的索引的方法:np.where()
np.where ( x > 5 ) #数组x中,大于5的元素的索引 np.where ( func(x) )#数组x中,使func返回True的元素的索引
返回值为索引,存储形式为,4.1节整数数组索引。比如一个二维数组,返回值就为x索引数组与y索引数组的组合
例子:
x=np.arange(9).reshape(3,3) np.where( x > 3 ) (array([1, 1, 2, 2, 2], dtype=int64), array([1, 2, 0, 1, 2], dtype=int64))
第一个为x索引,第二个为y索引,二者一一对应得到实际二维索引。
可直接用该索引提取数组元素:
y = np.where( x > 3 ) x[y] array([4, 5, 6, 7, 8]) #这等价于 x[ x > 3 ]
所以要提取元素的话,直接用布尔索引即可,而要提取元素索引的话,就要用到np.where了
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性