目录
- 一.Numpy 入门
- 1.开发环境安装与配置
- 2.NumPy数组引出
- 3.NumPy数组创建
- 4.NumPy数组查看
- 5.NumPy数据保存
- 6.NumPy数据类型
- 7.NumPy数组运算
- 8.NumPy索引与切片
- 9.训练场
- 9.1 创建一个长度为10的一维全为0的ndarray对象,然后让第5个元素等于1
- 9.2 创建一个元素为从10到49的ndarray对象,间隔是1
- 9.3 将第2题的所有元素位置反转
- 9.4 使用np.random.random创建一个10*10的ndarray对象,并打印出最大最小元素
- 9.5 创建一个10*10的ndarray对象,且矩阵边界全为1,里面全为0
- 9.6 创建一个每一行都是从0到4的5*5矩阵
- 9.7 创建一个范围在(0,1)之间的长度为12的等差数列,创建[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]等比数列。
- 9.8 创建一个长度为10的正太分布数组np.random.randn并排序
- 9.9 创建一个长度为10的随机数组并将最大值替换为-100
- 9.10 如何根据第3列大小顺序来对一个5*5矩阵排序?
- 二、Numpy 高级
- 1.数据形状改变
- 2.广播机制
- 3.通用函数
- 4.矩阵运算
- 5.训练场
- 5.1 给定一个4维矩阵,如何得到最后两维的和?(提示,指定axis进行计算)
- 5.2 给定数组[1, 2, 3, 4, 5],如何得到在这个数组的每个元素之间插入3个0后的新数组?
- 5.3 给定一个二维矩阵(5行4列),如何交换其中两行的元素(提示:任意调整,花式索引)?
- 5.4 创建一个100000长度的随机数组,使用两种方法对其求三次方(1、for循环;2、NumPy自带方法),并比较所用时间
- 5.5 创建一个5行3列随机矩阵和一个3行2列随机矩阵,求矩阵积
- 5.6 矩阵的每一行的元素都减去该行的平均值(注意,平均值计算时指定axis,以及减法操作时形状改变)
- 5.7 打印出以下函数(要求使用np.zeros创建8*8的矩阵):
- 5.8 正则化一个5行5列的随机矩阵(数据统一变成0~1之间的数字,相当于进行缩小)
- 5.9 如何根据两个或多个条件过滤numpy数组。加载鸢尾花数据,根据第一列小于5.0并且第三列大于1.5作为条件,进行数据筛选。(提示,需要使用逻辑与运算:&)
- 5.10 计算鸢尾花数据每一行的softmax得分(exp表示自然底数e的幂运算)
一.Numpy 入门
NumPy(Numerical Python)是Python的一种开源的数值计算扩展。提供多维数组对象,各种派生对象(如掩码数组和矩阵),这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库,包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。
几乎所有从事Python工作的数据分析师都利用NumPy的强大功能。
a.强大的N维数组
b.成熟的广播功能
c.用于整合C/C++和Fortran代码的工具包
d.NumPy提供了全面的数学功能、随机数生成器和线性代数功能
1.开发环境安装与配置
🚩有两种不同的安装手段,本文主要介绍第二种方法,并提供两种下载渠道:
第一种方式:
在 cmd 中输入下面两行:
pip install jupyter -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
第二种方式:
直接安装Anaconda下载:Anaconda Installers
读者根据自己不同的操作系统进行下载,博主为 Windows 系统,下面安装流程也是在 Windows 操作系统上进行,不过区别不大。
也可以直接在百度网盘下载:Anaconda Installers,提取码:3h2u
❗️ 注意:Add Path!!! 添加一下环境变量~
进入等待:
安装完成~
这时会弹出两个网站:
不用管,直接关闭即可。
我们进入 cmd,输入:
jupyter notebook
紧接着会进入一个网站:
至此,我们的 Anaconda 安装成功,Congratulation~🎈
我们在这里新建一个文件夹:
此时的文件是未命名的,我们来给它起个名字:
我们在 AIoT 中创建一个 Python3:
我们还是一样给它改个名:
至此,我们成功创建了 Python3 文件,Congratulation~🎈
2.NumPy数组引出
🚩下面我们就开始写代码:
写完一行之后我们点击运行,同样用快捷键:Shift + Enter
也可以运行:
如下可以查看所有的快捷键:
我们的代码是可以反复运行的:比如我们再运行一下第一行代码,就会发现,从 In [1] 变成了 In[2]:
现在我们让它变成蓝色:
很丑,对吧,因为在 Python 语法中,#
代表的是注释,而在 Markdown 中,#
代表的是一级标题。
故我们可以去掉 #
按下快捷键:B
,继续写代码
没有行号看起来是不是有些别扭?我们点击 view -> line numbers:
我们编写一个代码,输出一个列表,我们点击运行:
当然我们的切片操作也是一样的:
我们的主角登场了!numpy数组
numpy数组支持更简单的操作:
比如我们的列表,下述操作会报错:
但是我们的numpy数组就支持上述操作:
当然,还有一些很“离谱”的操作:
显然,我们的列表是没有这种“骚操作”的:
3.NumPy数组创建
🚩我们在 1.2 NumPy数组引出 其实已经简单给大家介绍了如何创建一个数组:使用 array 函数.
但其实,创建数组的方式不仅如此,NumPy 中有很多的方式去创建(初始化)一个数组:
我们发现这个 logspace 的运行结果我们看不懂,这是因为它是用科学计数法表达的,我们可以使用 np.set_printoptions(suppress = True)
来让运行结果变成我们能看懂的数字:
上述代码:
np.ones(shape = 10) # 10个1
np.zeros(shape = 5) # 5个0
np.full(shape = 6, fill_value = 666) # 6个666
np.random.randint(0, 100, size = 10) # 在0 ~ 100 中随机生成10个数
np.random.randn(10) # 生成10个正态分布,平均值是0,标准差是1
np.linspace(1, 100, 100) # 把1 ~ 100等分成100份(等差数列)
np.linspace(1, 99, 50)
np.set_printoptions(suppress = True)
np.logspace(0, 10, base = 2, num = 11)# 从2^0 到 2^ 10 分成11份
# 使用 shift + tab 可以查看方法的参数,工具查看
# 二维数组:3行5列
np.random.randint(0, 10, size = (3, 5))
# 三维数组:
np.random.randint(0, 10, size = (2, 3, 5))
4.NumPy数组查看
🚩jupyter扩展插件(也可以不安装)
在我们的 cmd 中输入以下指令:
pip install jupyter_contrib_nbextensions -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install jupyter_nbextensions_configurator -i https://pypi.tuna.tsinghua.edu.cn/simple
jupyter contrib nbextension install --user
jupyter nbextensions_configurator enable --user
安装好后退出,重新进入jupyter notebook:
勾选如下:
安装好之后,再次进入我们的代码,会发现多了一个这个东西:
点击即可出现一个索引目录:
4.1 数组的维度
import numpy as np
arr = np.random.random(size = (3, 5))
arr.ndim # 维度
4.2 数组的形状
import numpy as np
arr = np.random.random(size = (3, 5))
arr.shape # 形状
4.3 数组元素的总数
import numpy as np
arr = np.random.random(size = (3, 5))
arr.size # 数组元素的总数
4.4 数据类型
import numpy as np
arr = np.random.random(size = (3, 5))
arr.dtype # 数据类型 float64 (64位)
4.5 数组中每个元素的大小(以字节为单位)
import numpy as np
arr = np.random.random(size = (3, 5))
# 0, 1 -----> 位
# 8个位 -----> 字节
# 64 / 8 = 8
arr.itemsize # 每个元素的大小,对应8个字节
5.NumPy数据保存
🚩我们可以使用 save 方法去保存我们的数组:
import numpy as np
arr = np.arange(0, 10, 3) # NumPy 的方法,功能类似
# 当前目录
np.save('./data1', arr) # 保存
运行后我们返回到创建好的目录下:
可以发现多了一个 data1.npy
这里面就是我们刚刚保存的数组信息。
注意,如果你点开新建立的这个文件的话,会发现:
里面并没有我们想看到的存储信息,这是因为文件保存的内容是二进制的,只能使用代码去打开,下面我们介绍从文件中读取我们的数据的方法:
我们按照下述代码可以取出数据:
import numpy as np
arr = np.arange(0, 10, 3) # NumPy 的方法,功能类似
np.load('./data1.npy') # 取出数据
如果我们要把多个数组存入一个文件,可以使用 savez 方法:
import numpy as np
arr = np.arange(0, 10, 3) # NumPy 的方法,功能类似
np.set_printoptions(suppress = True)
arr2 = np.logspace(0, 10, base = 2, num = 11)
np.savez('./data2.npz', x = arr, y = arr2)
# 把arr和arr2都存入'./data2.npz'
# 把arr存入,起名为x;把arr2存入,起名为y
运行后,可以看到多了一个 data2.npz
文件,这里面就是我们刚刚保存的数组信息。
我们在取值的时候可以一个一个取:
import numpy as np
arr = np.arange(0, 10, 3) # NumPy 的方法,功能类似
np.set_printoptions(suppress = True)
arr2 = np.logspace(0, 10, base = 2, num = 11)
np.load('./data2.npz')['x'] # 取出 x ---> 取出 arr
np.load('./data2.npz')['y'] # 取出 y ---> 取出 arr2
注意我们存的时候用什么名,取的时候就用什么名,比如:
显然在这个时候取出 y
的话就是错误的。
读写csv、txt文件:
import numpy as np
arr = np.random.randint(0, 10, size = (3, 4))
# 储存数组到csv文件
np.savetxt("./arr.csv", arr, delimiter = ',') # 存储到txt文件也一样
# 读取文件
np.loadtxt('./arr.csv', delimiter = ',', dtype = np.int32)
6.NumPy数据类型
🚩我们的数据类型包涵三大类:
整数
浮点数
字符串
ndarray的数据类型:
-
int(整数):
int8、uint8、int16、int32、int64
-
float(浮点数):
float16、float32、float64
-
str(字符串)
float16 float32
,int16 int 32
有什么不同:数字越大,证明其在内存中所占内存越大,当然相应的,可以表示的数的范围也就越大:如 int8 的范围大小为 28,但是因为它既包含正数也包含负数,故它其实可以表达的范围就是 [-128, 127] ,unit8 的范围也是 28,不同的是它不包含负数即只包含0和正数,故 unit8 的取值范围就是 [0, 255],使用 astype() 方法可以转换数据类型:
我们在创建类型的时候,可以用dtype
指明它的数据类型
当然,我们还可以给它为 int32:
我们输入如下代码,编译运行:
然后返回到我们的文件夹查看我们刚刚保存的两个文件:
很直观的可以注意到,两个文件的大小相差大致为8倍,这个的原因其实就是 64 / 8 = 8
使用 astype() 方法可以转换数据类型:
这里我们需要注意,转换之后,原数组的数据类型是不变的,使用astype()进行转换可以说是创建了一个新的数组:
7.NumPy数组运算
🚩数组运算包含一个数组元素内的运算以及两个或多个数组之间的运算:
7.1 加减乘除幂运算
我们在算次方的时候也可以调用 power() 函数
当然还有还支持 / 和 % 运算
两个数组的运算,其实就是对应位置的运算:
import numpy as np
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([2, 4, 4, 6, 6])
print(arr1 - arr2) # 减法
print(arr1 + arr2) # 加法
print(arr1 * arr2) # 乘法
print(arr1 / arr2) # 除法
print(arr1 ** arr2) # 幂运算
7.2 逻辑运算
当然,两个数组之间也有逻辑运算:
7.3 += -= *= 操作
❗️ 注意:上述的操作并没有改变数组的原值,可以理解为重新创建了一个新的数组,但是下面的操作,是直接在数组的基础上进行修改,会改变数组的元素的值
注意,这里不包含 /= 运算,会报错,在这里为 //=:
8.NumPy索引与切片
🚩索引和切片操作其实我们在列表中是经常使用的,这里不再进行过多的赘述,讲解在 NumPy 中实现索引查找和切片操作
8.1 一维数组索引和切片
8.2 二维数组索引和切片
如果我们想取出多行多列的数据又该怎么操作呢?
很明显能看出,输出的结果并不是我们想要输出的,这是因为,如果我们要取出多行多列,需要索引和切片相配合使用:
你可能有点懵逼,没事儿,咋们多举几个例子:
咋们回头看看刚刚的错误操作取出来的到底是什么:
不难看出咋们取的是 (1, 3) 和 (2, 4) 位置的值
❗️ 接下来就开始骚操作:如果行和列不是连续的行和列该怎么取呢?比如我想取第一行,第三行以及第二列,第四列的数:
接下来介绍另一种方法,也可以实现:
我们也可以更改数组中的值,我们只需要找到相应的索引即可:
当然,我们可以一次性更改多个值:
8.3 花式索引
所谓花式索引,其实就是一次性取出多个值
9.训练场
🚩训练场中包含十道例题以及答案代码,读者需要自己敲写一遍,已增强学习记忆。
在这里,给大家介绍一个函数:display() 它的作用类似于 print() 函数,不过它相较于 print 而言更加的美观:
9.1 创建一个长度为10的一维全为0的ndarray对象,然后让第5个元素等于1
# 创建一个长度为10的一维全为0的ndarray对象,然后让第5个元素等于1
import numpy as np
arr = np.zeros(10, dtype = 'int')
# 第5个
arr[4] = 1
arr
9.2 创建一个元素为从10到49的ndarray对象,间隔是1
# 创建一个元素为从10到49(包含49)的ndarray对象,间隔是1
import numpy as np
# 注意是包含 49 的,故我们在给函数串参数的时候需要传到 50
arr = np.arange(10, 50)
arr
9.3 将第2题的所有元素位置反转
# 将第2题的所有元素位置反转
import numpy as np
# 注意是包含 49 的,故我们在给函数串参数的时候需要传到 50
arr = np.arange(10, 50)
arr
# 使用反向切片操作可以使元素实现翻转
arr = arr[::-1]
arr
9.4 使用np.random.random创建一个10*10的ndarray对象,并打印出最大最小元素
# 使用np.random.random创建一个10*10的ndarray对象,并打印出最大最小元素
import numpy as np
arr = np.random.random(size = (10, 10))
# 使用 max 和 min 分别计算最大和最小元素
print('最大值为:', arr.max())
print('最小值为:', arr.min())
9.5 创建一个10*10的ndarray对象,且矩阵边界全为1,里面全为0
# 创建一个10*10的ndarray对象,且矩阵边界全为1,里面全为0
import numpy as np
arr = np.full(shape = (10, 10), fill_value = 0, dtype = np.int8)
# 第一行和最后一行赋值为 1
arr[[0, -1]] = 1
# 第一列和最后一列赋值为 1
arr[:, [0, -1]] = 1
arr
9.6 创建一个每一行都是从0到4的5*5矩阵
# 创建一个每一行都是从0到4的5*5矩阵
import numpy as np
# 先创建一个元素全为 0 的矩阵
arr = np.zeros((5, 5), dtype = int)
# 依次加值
arr += np.arange(5)
arr
9.7 创建一个范围在(0,1)之间的长度为12的等差数列,创建[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]等比数列。
# 创建一个范围在(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)
# 等比数列
arr2 = np.logspace(0, 10, base = 2, num = 11, dtype = int)
arr2
9.8 创建一个长度为10的正太分布数组np.random.randn并排序
# 创建一个长度为10的正太分布数组np.random.randn并排序
import numpy as np
# 创建一个随机数组
arr = np.random.randn(10)
print('未排序:', arr)
# 调用 np.sort() 方法,需要一个新数组去接受数据
arr2 = np.sort(arr)
print('排序后:', arr2)
9.9 创建一个长度为10的随机数组并将最大值替换为-100
# 创建一个长度为10的随机数组并将最大值替换为-100
import numpy as np
# 不使用科学计数法
np.set_printoptions(suppress = True)
# 创造随机数组
arr = np.random.random(10)
print('原数据:', arr)
# 找到最大值
Max = arr.max()
# 进行条件判断
cnt = arr == Max
# 更改赋值
arr[cnt] = -100
# 输出更改后的数组
print('更改后:', arr)
9.10 如何根据第3列大小顺序来对一个5*5矩阵排序?
# 如何根据第3列大小顺序来对一个5*5矩阵排序?(考察argsort()方法)
import numpy as np
# 先来讲解 argsort() 方法:
arr = np.random.randint(0, 100, size = 5)
display(arr)
# argsort() 的作用是返回排序后的索引下标
index = np.argsort(arr)
display(index)
# 根据索引进行排序:花式索引
arr[index]
import numpy as np
# 返回到题目要求之中
arr = np.random.randint(0, 30, size = (5, 5))
display(arr)
# 获取第三列的索引顺序
index = arr[:, 2].argsort()
# 根据第三列的索引顺序,对 arr 进行排序
arr[index]
二、Numpy 高级
1.数据形状改变
1.1 数组变形
🚩我们可以使用 reshape() 方法,把数组任意的进行形状的变化:
import numpy as np
nd2 = np.random.randint(0, 100, size = (3, 4))
display(nd2)
# 数据重塑 reshape
# 我们的 nd2 是一个三行四列的数组,我们可以把它变成四行三列
display(nd2.reshape(4, 3))
# 再来举例,我们把它变成两行六列
# 方法一:
display(nd2.reshape(2, 6))
# 方法二:
display(nd2.reshape(-1, 6))
# -1 表示的是最后计算:相当于 x * 6 = 3 * 4 ---> x = 2
# -1 适合不关心总数的情况,不关心总数是多少,比较灵活
display(nd2.reshape(-1))
# 相当于 x = 3 * 4 ---> x = 12
1.2 数组堆叠
🚩我们可以使用 concatenate() 进行数组的合并:
arr1 = np.random.randint(0, 10, size = (2, 4))
arr2 = np.random.randint(0, 10, size = (2, 4))
display(arr1, arr2)
# 合并,默认进行(xing)行(hang)合并
display(np.concatenate([arr1, arr2]))
# 我们还可以合并多个
display(np.concatenate([arr1, arr2, arr1]))
那么我们是否可以合并一个三行四列的数组和一个四行三列的数组呢?
真的没有办法了么?其实不然,我们通过观察这两个数组可以发现,虽然这两个数组的列数不同,但是这两个数组的行数是相同的,故我们可以进行列合并:
arr1 = np.random.randint(0, 10, size = (3, 5))
arr2 = np.random.randint(0, 10, size = (3, 4))
display(arr1, arr2)
# axis = 0(默认值),代表行
# axis = 1表示列,-1也可以表示
display(np.concatenate([arr1, arr2], axis = 1))
display(np.concatenate([arr1, arr2], axis = -1))
1.3 数组拆分
🚩使用 split() 函数可以把数组进行拆分:
nd = np.random.randint(0, 100, size = (6, 9))
display(nd)
# 行拆分
display(np.split(nd, 2)) # 平均拆分为2份
display(np.split(nd, 3)) # 平均拆分为3份
我们还可以不是平均拆分:
nd = np.random.randint(0, 100, size = (6, 9))
display(nd)
# 列表表示按节点进行拆分
np.split(nd, [1, 4, 5])
# 1 切一刀,4 切一刀,5 切一刀
# 分成了 [0, 1) [1, 4) [4, 5) [5, 6)
我们不仅可以拆分行,也可以拆分列,还是和 2.1.2 数组堆叠 一样,参数 axis = 0(默认值),代表行
,axis = 1,代表列
nd = np.random.randint(0, 100, size = (6, 9))
display(nd)
np.split(nd, 3, axis = 1) # 平均拆成三分(列拆分)
# 列表表示按节点进行拆分
np.split(nd, [1, 4, 5], axis = 1)
# 1 切一刀,4 切一刀,5 切一刀
# 分成了 [0, 1) [1, 4) [4, 5) [5, 9)
1.4 数组转置
🚩对于数组的转置,我们可以利用 T 进行转置,也可以使用 numpy 中的 transpose() 方法:
A = np.random.randint(0, 10, size = (3, 5))
display(A)
# 所谓转置就是行变列,列边行
display(A.T)
# 还可以按照下面的方法进行转置
display(np.transpose(A, axes = [1, 0]))
2.广播机制
🚩所谓广播,就是对原本数据的不断复制,复制到和目标数组相同的构造的时候,比如我们有一个三行四列的数组,要加一行四列的数组,那么一行四列的数组就会自己复制三份,变成三行四列的数组,其中每一行都和原本数组的值相同,变成这种形式之后,再和原三行四列的数组进行相加运算,下面,我们从三个方面进行代码演示:一维数组的广播,二维数组的广播,三维数组的广播。
2.1 一维数组的广播
arr1 = np.random.randint(0, 10, size = (5, 3))
arr2 = np.arange(1, 4)
display(arr1, arr2)
# arr1 有五行,arr2 只有一行
# 它们俩的相加就是通过广播机制
# 广播机制:arr2 变身,变成了五份(一模一样)
# 每一份对应每一行的相加
arr1 + arr2
2.2 二维数组的广播
arr3 = np.random.randint(0, 10, size = (4, 5))
# 计算每一行的平均值
arr4 = arr3.mean(axis = 1)
display(arr3, arr4)
# 注意 arr3 每一行5个数,arr4一行中为4个数
arr3 - arr4 # 形状不匹配,所以报错
因为形状不匹配的原因,故会报错,我们可以使用 2.1.1 数组变形 中的 reshape() 方法,对数组进行更改:
arr3 = np.random.randint(0, 10, size = (4, 5))
# 计算每一行的平均值
arr4 = arr3.mean(axis = 1)
display(arr3, arr4)
# 形状改变,arr4改为了四行一列
display(arr4.reshape(4, 1))
# arr3为四行五列
arr3 - arr4.reshape(4, 1)
2.3 三维数组的广播
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)
print('三维数组:')
display(arr1)
print('二维数组:')
display(arr2)
arr3 = arr1 + arr2 # arr2数组在0维上复制3份 shape(3,4,2)
arr3
3.通用函数
3.1 元素级数字函数
🚩NumPy 中和数学相关的函数有很多:abs、sqrt、square、exp、log、sin、cos、tan,maxinmum、minimum、all、any、inner、clip、round、trace、ceil、floor,下面我们挑几个常用的进行代码演示,感兴趣的读者可以自己搜索其他函数的用法并实践,这里不做过多演示:
# 圆周率
display(np.pi)
# 计算 sin90°
display(np.sin(90)) # 这是不合法的,90是int型,而非度数
display(np.sin(np.pi / 2)) # pi 是 180°,故 pi / 2 就代表 90°
# 计算 cos90°
display(np.cos(np.pi / 2))
一个很有意思的现象出现了,计算 cos90°的结果并不显示0,而是显示e-7,这是因为我们在计算的过程中会有精度问题,故我们一般表示0即当一个数小于一个很小的数的时候,我们就认为这个数为0,我们可以使用 round(n) 函数让它保留n位小数:
# 保留一位小数:
display(np.cos(np.pi / 2).round(1))
# 保留五位小数:
display(np.cos(np.pi / 2).round(5))
可以看到,就算我们保留五位小数,依旧是0,故我们认为这个数是0
# 开平方
display(np.sqrt(1024))
# 平方
display(np.square(8))
# 幂运算
display(np.power(2, 3)) # 计算2的3次方
# log运算
display(np.log2(16)) # 计算log以2为底16的对数
# 依次比较两个等长数组,返回对应位置元素的最大值
x = np.array([6, 6, 0, 7, 2, 5])
y = np.array([9, 5, 6, 3, 4, 2])
display(np.maximum(x, y))
# 依次比较两个等长数组,返回对应位置元素的最小值
x = np.array([6, 6, 0, 7, 2, 5])
y = np.array([9, 5, 6, 3, 4, 2])
display(np.minimum(x, y))
# 返回一维数组向量内积
arr = np.random.randint(0, 10, size = (2, 2))
display(arr)
np.inner(arr[0], arr)
a = 6.66666
# 向上取整
display(np.ceil(a))
# 向下取整
display(np.floor(a))
# 裁剪,小于就拔高,大于就降低
arr = np.random.randint(0, 30, size = 20)
display(arr)
# 10:小于10:变成10;
# 20:大于20:变成20
np.clip(arr, 10, 20)
3.2 where函数
import numpy as np
arr1 = np.array([9, 7, 9, 9, 6])
arr2 = np.array([2, 1, 2, 0, 6])
cnt = np.array([False, False, True, False, True])
# 根据条件进行筛选
display(np.where(cnt,arr1,arr2)) # True选择arr1,False选择arr2的值
arr3 = np.random.randint(0, 30, 20)
display(arr3)
# 如果 arr3 的元素值小于15就输出,否则输出-15
display(np.where(arr3 < 15, arr3, -15))
3.3排序方法
🚩NumPy中还提供了排序方法,排序方法是就地排序,即直接改变原数组:
arr.sort()、np.sort()、arr.argsort()
import numpy as np
arr = np.array([14, 9, 13, 13, 18, 18, 18, 7, 5, 11])
# 直接让原数组从小到大进行排序
arr.sort()
display(arr)
# 返回深拷贝排序结果
np.sort(arr)
arr = np.array([14, 9, 13, 13, 18, 18, 18, 7, 5, 11])
display(arr)
# 返回从小到大排序的索引
display(arr.argsort())
3.4 集合运算函数
A = np.array([6, 8, 9, 1, 4])
B = np.array([3, 6, 5, 7, 1])
# 计算交集
display(np.intersect1d(A, B))
# 计算并集
display(np.union1d(A, B))
# 计算差集
display(np.setdiff1d(A, B))
3.5数学和统计函数
🚩我们挑几个常用的函数进行代码演示,剩余的函数有兴趣的读者可以自行查阅用法自己演示。min、max、mean、median、sum、std、var、cumsum、cumprod、argmin、argmax、argwhere、cov、corrcoef
import numpy as np
arr1 = np.array([5, 90, 87, 35, 23, 6, 39, 39, 99, 79, 72, 94, 97, 13, 84])
# 计算数组中的最小值
display(arr1.min())
# 计算数组中的最大值的索引
display(arr1.argmax())
# 返回大于40的元素的索引
display(np.argwhere(arr1 > 40))
# 计算数组的累加和
display(np.cumsum(arr1))
arr2 = np.random.randint(0, 10,size = (4, 5))
display(arr2)
# 计算列的平均值
display(arr2.mean(axis = 0))
# 计算行的平均值
display(arr2.mean(axis = 1))
# 协方差矩阵
display(np.cov(arr2, rowvar = True))
# 相关性系数
display(np.corrcoef(arr2, rowvar = True))
4.矩阵运算
4.1 矩阵的乘法
#矩阵的乘积(点乘)
A = np.array([[2, 1, 7],
[6, 3, 4]]) # shape(2, 3)
B = np.array([[4, 3],
[0, 9],
[-5, -8]]) # shape(3, 2)
# 第一种方法
display(np.dot(A,B))
# 第二种方法
display(A @ B) # 符号 @ 表示矩阵乘积运算
# 第三种方法
display(A.dot(B))
4.2 矩阵的其他运算
np.set_printoptions(suppress = True) # 不使用科学计数法
from numpy.linalg import inv,det,eig,qr,svd
A = np.array([[1, 2, 3],
[2, 3, 1],
[3, 2, 1]]) # shape(3, 3)
# 求逆矩阵
B = inv(A) # B 就是 A 的逆矩阵
display(B)
display(A.dot(B))
# 求矩阵的行列式
display(det(A))
5.训练场
5.1 给定一个4维矩阵,如何得到最后两维的和?(提示,指定axis进行计算)
import numpy as np
arr = np.random.randint(0, 10, size = (2, 3, 4, 5))
display(arr)
display(arr.sum(axis = 0)) # 第0维的数据进行加和
display(arr.sum(axis = 1)) # 第1维的数据进行加和
display(arr.sum(axis = -1)) # 最后一维的数据进行加和
# 最后两维的和
# 写法一:
display(arr.sum(axis = (-1, -2)))
# 写法二:
display(arr.sum(axis = (2, 3)))
5.2 给定数组[1, 2, 3, 4, 5],如何得到在这个数组的每个元素之间插入3个0后的新数组?
import numpy as np
arr1 = np.arange(1, 6)
display(arr1)
# 每个元素之间插入3个0,共插入3*4=12个0
# 再加上初始的5个值,共需要17个位置
# 创建一个长度为17的全部是0的数组
arr2 = np.zeros(shape = 17, dtype = np.int16)
display(arr2)
# 有间隔的,每4个取一个,取出数据并进行替换
arr2[::4] = arr1
display(arr2)
5.3 给定一个二维矩阵(5行4列),如何交换其中两行的元素(提示:任意调整,花式索引)?
import numpy as np
arr = np.random.randint(0, 100, size = (5, 4))
display(arr)
# 使用花式索引进行交换
arr = arr[[0, 2, 1, 3, 4]]
display(arr)
5.4 创建一个100000长度的随机数组,使用两种方法对其求三次方(1、for循环;2、NumPy自带方法),并比较所用时间
%%time
:可以显示代码的运行时间,这个执行时间会和电脑的性能挂钩
使用 for 循环
%%time
import numpy as np
arr = np.random.randint(0, 10, size = 100000)
res = []
for item in arr:
res.append(item ** 3)
使用NumPy自带方法
%%time
import numpy as np
arr = np.random.randint(0, 10, size = 100000)
res = []
arr2 = np.power(arr, 3)
可以发现,使用 NumPy 自带方法运行效率要远远高于使用 for 循环
5.5 创建一个5行3列随机矩阵和一个3行2列随机矩阵,求矩阵积
import numpy as np
A = np.random.randint(0, 10, size = (5, 3))
B = np.random.randint(0, 10, size = (3, 2))
display(A, B)
# 调用 NumPy 函数 dot
print('方式一:\n', np.dot(A, B))
# 调用对象方法
print('方式二:\n', A.dot(B))
# 使用符号计算
print('方式三:\n', A @ B)
5.6 矩阵的每一行的元素都减去该行的平均值(注意,平均值计算时指定axis,以及减法操作时形状改变)
import numpy as np
A = np.random.randint(0, 10, size = (4, 5))
display(A)
# 计算每一行的平均值:
B = A.mean(axis = 1)
display(B)
# 需要注意,我们计算的平均值是一行四列
# 但是我们要让每一行的元素都减去该平均值
# 这就需要我们让其形状改变为四列一行
B = B.reshape(-1, 1)
# 然后利用广播机制,即可进行计算
display(A - B)
5.7 打印出以下函数(要求使用np.zeros创建8*8的矩阵):
[[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]
[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]
[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]
[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]]
import numpy as np
arr = np.zeros(shape = (8, 8), dtype = np.int16)
# 将奇数行进行修改
arr[::2, 1::2] = 1
# 将偶数行进行修改
arr[1::2, ::2] = 1
display(arr)
5.8 正则化一个5行5列的随机矩阵(数据统一变成0~1之间的数字,相当于进行缩小)
正则的概念:矩阵A中的每一列减去这一列最小值,除以每一列的最大值减去每一列的最小值(提示:
轴axis给合适的参数!!!)
A = A − A . m i n A . m a x − A . m i n \rm{A = \frac{A - A.min}{A.max - A.min}} A=A.max−A.minA−A.min
import numpy as np
A = np.random.randint(1, 10, size = (5, 5))
display(A)
# axis = 1 代表行
display(A.min(axis = 1))
# axis = 0 代表列
display(A.min(axis = 0))
# 根据公式计算
B = (A - A.min(axis = 0)) / (A.max(axis = 0) - A.min(axis = 0))
display(B)
5.9 如何根据两个或多个条件过滤numpy数组。加载鸢尾花数据,根据第一列小于5.0并且第三列大于1.5作为条件,进行数据筛选。(提示,需要使用逻辑与运算:&)
我们的数据:
链接:https://pan.baidu.com/s/1VaPHJa6YttfnedO0ewDRtQ
提取码:5u92
我们在下载好数据之后,把它移入到我们如下文件夹中:(直接下载到桌面后,找到该文件夹的位置,然后拖进去即可)
首先我们来介绍一下 .csv
文件,它其实就是一个文本文件,我们打开它(默认打开路径为Excel)
我们也可以选择打开方式为记事本方式:
通过观察不难看出,数据之间通过,
相隔
接下来介绍一个新方法:loadtxt()
,其作用为加载数据,比如:np.loadtxt('./iris.csv', delimiter = ',')
,其作用为打开路径'./iris.csv'
的文件,这些数据直接通过,
进行分隔。
import numpy as np
# 加载了文本文件,储存数据都是结构化数据
iris = np.loadtxt('./iris.csv', delimiter = ',')
display(iris)
可以看出,这些数据是以二维数组的形式展开的,每一维都有四个数据,分别代表:花萼长度,花萼宽度,花瓣长度,花瓣宽度
import numpy as np
# 加载了文本文件,储存数据都是结构化数据
# 花萼长度、花萼宽度、花瓣长度、花瓣宽度
iris = np.loadtxt('./iris.csv', delimiter = ',')
# 第一列小于5.0
cnt1 = iris[:, 0] < 5
# 第三列大于1.5
cnt2 = iris[:, 2] > 1.5
# 逻辑与运算
cnt = cnt1 & cnt2
display(iris[cnt])
5.10 计算鸢尾花数据每一行的softmax得分(exp表示自然底数e的幂运算)
import numpy as np
iris = np.loadtxt('./iris.csv', delimiter = ',')
def softmax(x):
exp = np.exp(x)
# 每一行求和,并且进行形状改变(变成二维,可进行广播)
# axis = 1 表示计算每一行的和
res = exp / exp.sum(axis = 1).reshape(-1, 1)
return res.round(3) # 保留3位小数
res = softmax(iris)
display(res)