NumPy(Numerical Python)是Python的一种开源的数值计算扩展。提供多维数组对象,各种派生对
象(如掩码数组和矩阵),这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested
list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵
运算,此外也针对数组运算提供大量的数学函数库,包括数学、逻辑、形状操作、排序、选择、输入输
出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。
- 使用需要安装numpy库(注意:首先要在电脑中安装的有python),安装方式如下:
(1)第一种方式:
pip install jupyter -i https://pypi.tuna.tsinghua.edu.cn/simple pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
然后在你想要存放文件的目录打开cmd输入:jupyter notebook
(2)第二种方式:
直接安装anaconda下载,它自带jupyter notebook(安装anaconda的过程中记得有个Add Path选项 一定要勾上,以免后面自己添加环境变量很麻烦)
- 前置知识
(1)如何启动终端
Windows----> 快捷键:win + R ----->输入:cmd回车------>命令行出来
Mac ---->启动终端
(2)启动jupyter notebook
进入终端输入指令:jupyter notebook
在哪里启动jupyter启动,浏览器上的目录,对应哪里,windows默认路径是:
C:Userslufengkun
C:Usersxxx
(3)jupyter notebook更过内容(例如扩展的使用,请阅读:https://blog.csdn.net/qq_34516746/article/details/124147543?spm=1001.2014.3001.5501)
创建数组的最简单的方法就是使用array函数,将Python下的list转换为ndarray。
import numpy as np l = [1,2,3,5,7,9] # 列表 arr = np.array(l) # 将Python下的list转换为ndarray arr# 数据一样,NumPy数组的方法,功能更加强大 # 输出为 # array([1, 3, 5, 7, 9])
我们可以利用np中的一些内置函数来创建数组,比如我们创建全0的数组,也可以创建全1数组,全是其
他数字的数组,或者等差数列数组,正态分布数组,随机数。
import numpy as np arr1 = np.ones(10) # 输出为:array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) arr2 = np.zeros(10) # 输出为: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) arr3 = np.full(shape = [2,3],fill_value=2.718) # 输出为: # array([[2.718, 2.718, 2.718], # [2.718, 2.718, 2.718]]) arr4 = np.arange(start = 0,stop = 20,step = 2) # 等差数列 输出为:array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]) arr5 = np.linspace(start =0,stop = 9,num = 10) # 等差数列 输出为:array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) arr6 = np.random.randint(0,100,size = 10) # int随机数 输出为:array([ 4, 8, 79, 62, 34, 35, 2, 65, 47, 18]) arr7 = np.random.randn(5) # 正态分布 输出为:array([ 0.57807872, 0.37922855, 2.37936837, -0.28688769, 0.2882854 ]) arr8 = np.random.random(size = 5) # float 随机数 输出为:array([0.59646412, 0.37960586, 0.38077327, 0.76983539, 0.22689201])2.2 查看操作
NumPy的数组类称为ndarray,也被称为别名 array。请注意,numpy.array这与标准Python库类不同
array.array,后者仅处理一维数组且功能较少。ndarray对象的重要属性是
- 数组的(1)轴数、(2)维数、(3)尺寸形状、(4)元素总数、(5)数组类型、(6)数组中每个元素的大小(以字节为单位)
import numpy as np
arr = np.random.randint(0,100,size=(3,4,5))
arr.ndim # 轴数 输出 3
arr.shape # 维数 输出 (3,4,5)
arr.shape # 尺寸形状 输出 (3,4,5)
arr.size # 元素总数 输出 3*4*5 = 60
arr.dtype # 数组类型 输出 dtype('int64')
arr.itemsize #输出是 8 ,因为数据类型是int64,64位,一个字节是8位,所以64/8 = 8
2.3 文件IO操作
2.3.1 保存数组
save方法保存ndarray到一个npy文件,也可以使用savez将多个array保存到一个.npz文件中
import numpy as np
x = np.random.randn(5)
y = np.arange(0,10,1)
#save方法可以存一个ndarray(保存路径在当前路径)
np.save("x_arr",x)
#如果要存多个数组,要是用savez方法,保存时以key-value形式保存,key任意(xarr、yarr)
np.savez("some_array.npz",xarr=x,yarr=y)
2.3.2 读取
load方法来读取存储的数组,如果是.npz文件的话,读取之后相当于形成了一个key-value类型的变量,通过保存时定义的key来获取相应的array
import numpy as np
np.load("x_arr.npy")
np.load("some_array.npz")["yarr"]
2.3.3 读写csv、txt文件
import numpy as np
arr = np.random.randint(0,10,size=(3,4))
# 储存数组到txt文件
np.savetxt("arr.csv",arr,delimiter=',') # 文件后缀是txt也是一样的
# 读取txt文件,delimiter为分隔符,dtype为数据类型
np.loadtxt("arr.csv",delimiter=',',dtype=np.int32)
3 数据类型的设置和转化
- ndarray的数据类型:
(1)int: int8、uint8、int16、int32、int64
(2)float: float16、float32、float64
(3)str
import numpy as np
# 1.array创建时,指定
arr = np.array([1,2,5,8,2],dtype='float32')
# 输出 :array([1., 2., 5., 8., 2.], dtype=float32)
# 2 asarray转换时指定
arr = [1,3,5,7,2,9,0]
# asarray 将列表进行变换
arr = np.asarray(arr,dtype='float32')
# 输出:array([1., 3., 5., 7., 2., 9., 0.], dtype=float32)
# 3 数据类型转换astype
arr = np.random.randint(0,10,size=5,dtype='int16')
# 输出:array([6, 6, 6, 6, 3], dtype=int16)
# 使用astype进行转换
arr = arr.astype(dtype='float32') # 输出:array([6., 6., 6., 6., 3.], dtype=float32)
# 注意astype一定要用一个变量来接受,它不是本地修改的
4 数组运算
- 加减乘除运算
import numpy as np arr1 = np.array([1,2,3,4,5]) arr2 = np.array([2,3,1,5,9]) arr1 - arr2 # 减法 arr1 * arr2 # 乘法 arr1 / arr2 # 除法 arr1 // arr2 # 除法只保留整数部分 arr1**arr2 # 两个星号表示幂运算
- 逻辑运算
import numpy as np arr1 = np.array([1,2,3,4,5]) arr2 = np.array([1,0,2,3,5]) arr1 < 5 # 输出:array([ True, True, True, True, False]) arr1 > 5 # 输出:array([False, False, False, False, False]) arr1 == 5 arr1 == arr2 arr1 > arr2
- 数组和标量(就是一个数)的计算
import numpy as np arr = np.arange(1,10) 1/arr arr+5 arr*5
- *=、+=、-=操作
某些操作(例如+=和=)只会修改现有数组,而不是创建一个新数组。
import numpy as np arr1 = np.arange(5) arr1 +=5 arr1 -=5 arr1 *=5 # arr1 /=5 不支持运算5 复制和视图
在操作数组时,有时会将其数据复制到新数组中,有时不复制。对于初学者来说,这通常会引起混乱。有以下三种情况
- 完全没有复制(两个是一个东西)
import numpy as np a = np.random.randint(0,100,size=(4,5)) b = a a is b # 返回True a和b是两个不同名字对应同一个内存对象 b[0,0] = 1024 # 命运共同体 display(a,b)
- 查看或者浅拷贝
不同的数组对象可以共享相同的数据。该view方法创建一个查看相同数据的新数组对象
import numpy as np a = np.random.randint(0,100,size=(4,5)) b = a.view() # 使用a中的数据创建一个新数组对象 a is b # 返回False a和b是两个不同名字对应同一个内存对象 b.base is a # 返回True,b视图的根数据和a一样 b.flags.owndata # 返回False b中的数据不是其自己的 a.flags.owndata # 返回True a中的数据是其自己的 b[0,0] = 1024 # a和b的数据都发生改变 display(a,b)
- 深拷贝
import numpy as np a = np.random.randint(0,100,size=(4,5)) b = a.copy() b is a # 返回False b.base is a # 返回False b.flags.owndata # 返回True a.flags.owndata # 返回True b[0,0] = 1024 # b改变,a不变,分道扬镳 display(a,b)
注意:copy应该在不再需要原来的数组情况下,切片后调用。例如:假设a是一个巨大的中间结果,而最
终结果b仅包含的一小部分a,则在b使用切片进行构造时应制作一个深拷贝:
import numpy as np a = np.arange(1e8) # 1*10的八次方这么大的数 b = a[::1000000].copy() # ::默认是从头导尾,每100万个数据取一个 del a # 不在需要a,删除占内存大的内存a b.shape # 输出:(100,)5 索引、切片和迭代 5.1 基本索引和切片
numpy中数组切片是原始数组的视图,这意味着数据不会被复制,视图上任何数据的修改都会反映到原
数组上。
import numpy as np arr = np.array([0,1,2,3,4,5,6,7,8,9]) arr[5] # 索引 输出 5 arr[5:8] # 切片输出:array([5, 6, 7]) arr[2::2] # 从索引2开始每两个中取一个 输出 array([2, 4, 6, 8]) arr[::3] # 不写索引默认从0开始,每3个中取一个 输出为 array([0, 3, 6, 9]) arr[1:7:2] # 从索引1开始到索引7结束,左闭右开,每2个数中取一个 输出 array([1, 3, 5]) arr[::-1] # 倒序 输出 array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0]) arr[::-2] # 倒序 每两个取一个 输出 array([9, 7, 5, 3, 1]) arr[5:8] = 12 # array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9]) # 切片赋值会赋值到每个元素上,与列表操作不同 temp = arr[5:8] temp[1] = 1024 arr # 输出:array([ 0, 1, 2, 3, 4, 12, 1024, 12, 8, 9])
对于二维数组或者高维数组,我们可以按照之前的知识来索引,当然也可以传入一个以逗号隔开的索引
列表来选区单个或多个元素
import numpy as np arr2d = np.array([[1,3,5],[2,4,6],[-2,-7,-9],[6,6,6]]) # 二维数组 shape(4,3) arr2d.shape arr2d # 输出: # array([[ 1, 3, 5], # [ 2, 4, 6], # [-2, -7, -9], # [ 6, 6, 6]]) arr2d[0,-1] #索引 等于arr2d[0][-1] 输出 5 arr2d[0,2] #索引 等于arr2d[0][2] == arr2d[0][-1] 输出 5 arr2d[:2,-2:] #切片 第一维和第二维都进行切片 等于arr2d[:2][:,1:] # 输出: # array([[3, 5], # [4, 6]]) arr2d[:2,1:] #切片 1 == -2 一个是正序,另个一是倒序,对应相同的位置 # 输出: # array([[3, 5], # [4, 6]])5.2 花式索引和索引技巧
- 整数数组进行索引即花式索引,其和切片不一样,它总是将数据复制到新数组中
import numpy as np # 一维 arr1 = np.array([1,2,3,4,5,6,7,8,9,10]) arr2 = arr1[[1,3,3,5,7,7,7]] arr2[-1] = 1024 # 二维 arr2d = np.array([[1,3,5,7,9],[2,4,6,8,10],[12,18,22,23,37],[123,55,17,88,103]]) arr2d.shape # shape(4,5) arr2d[[1,3]] # 获取第二行和第四行,索引从0开始的所以1对应第二行 # 输出 array([[ 2, 4, 6, 8, 10], # [123, 55, 17, 88, 103]]) arr2d[([1,3],[2,4])] # 相当于arr2d[1,2]获取一个元素,arr2d[3,4]获取另一个元素 # 输出为 array([ 6, 103]) # 选择一个区域 arr2d[np.ix_([1,3,3,3],[2,4,4])] # 相当于 arr2d[[1,3,3,3]][:,[2,4,4]] arr2d[[1,3,3,3]][:,[2,4,4]] # ix_()函数可用于组合不同的向量 # 第一个列表存的是待提取元素的行标,第二个列表存的是待提取元素的列标 # 输出为 # array([[ 6, 10, 10], # [ 17, 103, 103], # [ 17, 103, 103], # [ 17, 103, 103]])
- boolean值的索引
import numpy as np names = np.array(['softpo','Brandon','Will','Michael','Will','Ella','Daniel','softpo','Will','Brandon']) cond1 = names =='Will' cond1 # 输出array([False, False, True, False, True, False, False, False, True, False]) names[cond1] # array(['Will', 'Will', 'Will'], dtype='6 形状操作 6.1 数组变形90 # 找到所有大于90的索引,返回boolean类型的数组 shape(10,8),大于返回True,否则False arr[cond2] # 返回数据全部是大于90的
import numpy as np arr1 = np.random.randint(0,10,size=(3,4,5)) # 注意变形时,具体的元素数量一定要保持一致,必须时3*4*5 = 60个 arr2 = arr1.reshape(12,5) # 形状改变,返回新数组。 arr3 = arr1.reshape(-1,5) # 自动“整形”,自动计算 arr3 = arr1.reshape(-1,6)6.2 数组转置
import numpy as np arr1 = np.random.randint(0,10,size=(3,5)) # shape(3,5) arr1.T # shape(5,3) 转置 arr2 = np.random.randint(0,10,size=(3,6,4)) # shape(3,6,4) np.transpose(arr2,axes=(2,0,1)) # transpose改变数组维度 shape(4,3,6)6.3 数组堆叠
import numpy as np arr1 = np.array([[1,2,3]]) arr2 = np.array([[4,5,6]]) np.concatenate([arr1,arr2],axis=0) # 串联合并shape(2,3) axis = 0表示第一维串联 输出为 # array([[1, 2, 3], # [4, 5, 6]]) np.concatenate([arr1,arr2],axis=1) # shape(1,6) axis = 1表示第二维串联 输出为:array([[1, 2, 3, 4, 5, 6]]) np.hstack((arr1,arr2)) # 水平方向堆叠 输出为:array([[1, 2, 3, 4, 5, 6]]) np.vstack((arr1,arr2)) # 竖直方向堆叠,输出为: # array([[1, 2, 3], # [4, 5, 6]])6.4 split数组拆分
import numpy as np arr = np.random.randint(0,10,size=(6,5)) # shape(6,5) arr1,arr2 = np.split(arr,indices_or_sections=2,axis=0) # 在第一维(6)平均分成两份 display(arr1,arr2) np.split(arr,indices_or_sections=[2,3],axis=1) # 在第二维(5)以索引2,3为断点分割成 3份 np.vsplit(arr,indices_or_sections=3) # 在竖直方向平均分割成3份 np.hsplit(arr,indices_or_sections=[1,4]) # 在水平方向,以索引1,4为断点分割成3份7 广播机制
当两个数组的形状并不相同的时候,我们可以通过扩展数组的方法来实现相加、相减、相乘等操作,这
种机制叫做广播(broadcasting)。
- 一维数组的广播
import numpy as np arr1 = np.sort(np.array([0,1,2,3]*3)).reshape(4,3) #shape(4,3) arr2 = np.array([1,2,3]) # shape(3,) arr3 = arr1 + arr2 # arr2进行广播复制4份 shape(4,3) arr3
- 二维数组的广播
import numpy as np arr1 = np.sort(np.array([0,1,2,3]*3)).reshape(4,3) # shape(4,3) arr2 = np.array([[1],[2],[3],[4]]) # shape(4,1) arr3 = arr1 + arr2 # arr2 进行广播复制3份 shape(4,3) arr3
- 三维数组广播
import numpy as np arr1 = np.array([0,1,2,3,4,5,6,7]*3).reshape(3,4,2) #shape(3,4,2) arr2 = np.array([0,1,2,3,4,5,6,7]).reshape(4,2) #shape(4,2) arr3 = arr1 + arr2 # arr2数组在0维上复制3份 shape(3,4,2) arr38 通用函数 8.1 元素级数字函数
abs、sqrt、square、exp、log、sin、cos、tan,maxinmum、minimum、all、any、inner、clip、round、trace、ceil、floor
import numpy as np arr1 = np.array([1,4,8,9,16,25]) np.sqrt(arr1) # 开平方 np.square(arr1) # 平方 np.clip(arr1,2,16) # 输出 array([ 2, 4, 8, 9, 16, 16]) x = np.array([1,5,2,9,3,6,8]) y = np.array([2,4,3,7,1,9,0]) np.maximum(x,y) # 返回两个数组中的比较大的值 arr2 = np.random.randint(0,10,size = (5,5)) np.inner(arr2[0],arr2) #返回一维数组向量内积8.2 where函数
where 函数,三个参数,条件为真时选择值的数组,条件为假时选择值的数组
import numpy as np arr1 = np.array([1,3,5,7,9]) arr2 = np.array([2,4,6,8,10]) cond = np.array([True,False,True,True,False]) np.where(cond,arr1,arr2) # True选择arr1,False选择arr2的值 # 输出 array([ 1, 4, 5, 7, 10]) arr3 = np.random.randint(0,30,size = 20) np.where(arr3 < 15,arr3,-15) # 小于15还是自身的值,大于15设置成-158.3 排序方法
np中还提供了排序方法,排序方法是就地排序,即直接改变原数组
arr.sort()、np.sort()、arr.argsort()
import numpy as np arr = np.array([9,3,11,6,17,5,4,15,1]) arr.sort() # 直接改变原数组 np.sort(arr) # 返回深拷贝排序结果 arr = np.array([9,3,11,6,17,5,4,15,1]) arr.argsort() # 返回从小到大排序索引 array([8, 1, 6, 5, 3, 0, 2, 7, 4])8.4 集合运算函数
import numpy as np A = np.array([2,4,6,8]) B = np.array([3,4,5,6]) np.intersect1d(A,B) # 交集 array([4, 6]) np.union1d(A,B) # 并集 array([2, 3, 4, 5, 6, 8]) np.setdiff1d(A,B) #差集,A中有,B中没有 array([2, 8])8.5 数学和统计函数
min、max、mean、median、sum、std、var、cumsum、cumprod、argmin、argmax、argwhere、cov、corrcoef
import numpy as np arr1 = np.array([1,7,2,19,23,0,88,11,6,11]) arr1.min() # 计算最小值 0 arr1.argmax() # 计算最大值的索引 返回 6 np.argwhere(arr1 > 20) # 返回大于20的元素的索引 np.cumsum(arr1) # 计算累加和 arr2 = np.random.randint(0,10,size = (4,5)) # array([[6, 4, 9, 0, 6], # [8, 9, 4, 2, 7], # [9, 2, 2, 9, 2], # [1, 5, 7, 9, 5]]) arr2.mean(axis = 0) # 计算列的平均值 array([6. , 5. , 5.5, 5. , 5. ]) arr2.mean(axis = 1) # 计算行的平均值 array([5. , 6. , 4.8, 5.4]) np.cov(arr2,rowvar=True) # 协方差矩阵 np.corrcoef(arr2,rowvar=True) # 相关性系数9 线性代数 9.1 矩阵乘积
import numpy as np A = np.array([[4,2,3], [1,3,1]]) # shape(2,3) B = np.array([[2,7], [-5,-7], [9,3]]) # shape(3,2) np.dot(A,B) # 矩阵运算 A的最后一维和B的第一维必须一致 A @ B # 符号 @ 表示矩阵乘积运算9.2 矩阵的其他计算
from numpy.linalg import inv,det,eig,qr,svd
A = np.array([[1,0,0],
[0,2,0],
[0,0,3]]) # shape(3,3)
inv(A) # 逆矩阵
det(A)#计算矩阵行列式
10 练习实例
1、创建一个长度为10的一维全为0的ndarray对象,然后让第5个元素等于1
import numpy as np arr = np.zeros(10,dtype = 'int') # 注意第5个元素对应索引是4 arr[4] = 1 arr
2、创建一个元素为从10到49(包含49)的ndarray对象,间隔是1
import numpy as np # 注意,包含49,所以范围给的是10 ~ 50,可以取到10,但是取不到50 arr = np.arange(10,50) arr
3、将第2题的所有元素位置反转
import numpy as np # 注意,包含49,所以范围给的是10 ~ 50,可以取到10,但是取不到50 arr = np.arange(10,50) # 注意::-1表示切片颠倒,数据倒过来了 arr = arr[::-1] arr
4、使用np.random.random创建一个10*10的ndarray对象,并打印出最大最小元素
import numpy as np
# 生成0~1之间的随机小数
arr = np.random.random(size = (10,10))
# 考察函数使用
print('输出最大值:',arr.max())
print('输出最小值:',arr.min())
5、创建一个10*10的ndarray对象,且矩阵边界全为1,里面全为0
import numpy as np arr = np.full(shape = (10,10),fill_value=0,dtype=np.int) # 第一行和最后一行重新赋值为:1 arr[[0,-1]] = 1 # 第一列和最后一列重新赋值为:1 arr[:,[0,-1]] = 1 arr
6、创建一个每一行都是从0到4的5*5矩阵
import numpy as np # 创建的形状5*5全部是0的数组 arr = np.zeros((5,5)) # 进行赋值操作,值是0~4 arr += np.arange(5) # 输出显示 print(arr)
7、创建一个范围在(0,1)之间的长度为12的等差数列,创建[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]等比数列。
import numpy as np # 等差数列 arr = np.linspace(0,1,12) display(arr) # 等比数列,base = 2表示2的倍数 arr2 = np.logspace(0,10,base=2,num = 11,dtype='int') arr2
8、创建一个长度为10的正太分布数组np.random.randn并排序
import numpy as np
# 创建随机数组
arr = np.random.randn(10)
print('未排序:',arr)
# 注意调用np.sort()方法,要接收一下数据
# 原来的arr并没有改变
arr2 = np.sort(arr)
print('排序后:',arr2)
9、创建一个长度为10的随机数组并将最大值替换为-100
import numpy as np
# 设置不显示科学计数法,默认情况显示情况是:3.22449e-01
np.set_printoptions(suppress = True)
arr = np.random.random(10)
print('原数据:n',arr)
# 找到最大值
v = arr.max()
# 进行条件判断
cond = arr == v
# 根据条件,赋值
arr[cond] = -100
print('修改之后数据:n',arr)
10、如何根据第3列大小顺序来对一个5*5矩阵排序?(考察argsort()方法)
np.random.seed(10)
arr = np.random.randint(0,10,(5,5))
print('原始数据:n',arr)
# 查看第三列数据,并获取索引排序
print('第三列数据:', arr[:,2])
# argsort函数返回的是数组值从小到大的索引值
print('第三列数据的排序:',np.argsort(arr[:,2]))
# 根据第三列索引排序,进行重新索引
print('根据第三列大小排序:n',arr[np.argsort(arr[:,2])])



