一、科学计算库Numpy
numpy定义:一个开源的python科学计算库;
使用Numpy可以方便的使用数组、矩阵进行计算
包含线性代数、傅里叶变换、随机数生成大量函数
引入numpy包:
import numpy as np
# 查看版本
print(np.__version__)
Numpy创建数组
numpy.array(object,dtype = None,copy=True,order=None,subok=False,ndmin=0)
参数:
object:表示一个数组序列; (元组、数组、迭代对象(range())、生成器)
dtype:可选参数,通过它可以更改数组的数据类型;
copy:可选参数,当数据源是ndarray时表示数组能否被复制,默认是True;
order:可选参数,以哪种内存布局创建数组,有 3 个可选值,分别是 C(行序列)/F(列序列)/A(默认)。
ndmin:可选参数,用于指定数组的维度。
subok:可选参数,类型为bool值,默认False。为True,使用object的内部数据类型;
False:使用object数组的数据类型。
细节:
1、在ndarray中所有元素必须是同一类型,否则会自动向下转换,int->float->str。
# 创建数组——列表中元素类型不同 (整形、字符串、浮点型)列表中元素类型不同,全部转换为字符串;
array2 = np.array([1,1.5,3,4.5,'5'])
print(f"创建数组——列表中元素类型不同:{array2}")
# 输出:创建数组——列表中元素类型不同:['1' '1.5' '3' '4.5' '5']
# 创建数组——列表中元素类型不同(整形、字符串、浮点型)
array2 = np.array([1,1.5,3,4.5,'5'])
print(f"创建数组——列表中元素类型不同:{array2}")
# 输出:创建数组——列表中元素类型不同[1. 2. 3.14 5.1 6. ]
numpy实现两个数组相加:
# numpy实现两个数组相加
def numpy_sum(n):
'''numpy实现两个数组相加'''
a = np.arange(n) ** 2
b = np.arange(n) ** 3
print(f"数组a:{a}")
print(f"数组b:{b}")
return a + b
# 调用函数
print(f"数组a + 数组b = {numpy_sum(10)}")
二维数组:嵌套序列(列表,元组均可)
array4 = np.array([
[1,2,3],
('a','b','c')
])
print(f"二维数组:嵌套序列(列表,元组均可):{array4}")
# 输出:二维数组:嵌套序列(列表,元组均可):[['1' '2' '3']
['a' 'b' 'c']]
嵌套序列数量不一样,就会强制转换为一维
array5 = np.array([
[1,2,3],
('a','b','c','d')
])
print(f"嵌套序列数量不一样:{array5}") # 版本太高执行报错!!
设置dtype参数,默认自动识别
# 设置dtype参数,默认自动识别
array6 = np.array([1,2,3,4,5],dtype='float')
print(f"设置dtype参数为浮点类型:{array6}")
# 输出:设置dtype参数为浮点类型:[1. 2. 3. 4. 5.]
将浮点类型设置为整形,截取整数,去点小数(不会四舍五入)
# 将浮点类型设置为整形
array7 = np.array([1.1,2.2,3.14,5.9,6.8],dtype='int')
print(f"将浮点类型设置为整形:{array7}")
# 输出:将浮点类型设置为整形:[1 2 3 5 6]
设置copy参数,默认为True
当copy为False时,不会创建副本,两个变量会指向相同的内容地址,没有创建新的对象
# 设置copy参数,默认为True
array8 = np.array([1,2,3,4,5])
array9 = np.array(array8)
print('array8的内存地址:',id(array8),'array9的内存地址:',id(array9))
array9[0] = 10
print(array8)
# 输出:array8的内存地址: 2127738993712 array9的内存地址: 2127738994288
[1 2 3 4 5]
# 视图操作
array10 = np.array([1,2,3,4,5])
array11 = array10
print('array10的内存地址:',id(array10),'array11的内存地址:',id(array11))
array10[0] = 10
print(array11)
# 输出:array10的内存地址: 2224009559760 array11的内存地址: 2224009559760
[10 2 3 4 5]
ndmin 用于指定数组的维度
# ndmin 用于指定数组的维度
array12 = np.array([1,2,3,4,5,6],ndmin = 2)
print(f"ndmin 用于指定数组的维度:{array12}")
# 输出:ndmin 用于指定数组的维度:[[1 2 3 4 5 6]]
NumPy 创建区间数组
numpy.arange(start,stop,step,dtype)
参数:
star:起始值,默认为0
stop:终止值(不包含)
step:步长,默认为1
dtype:返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型
# NumPy 创建区间数组
array13 = np.arange(10)
print(f"NumPy 创建区间数组:{array13}")
# 输出:NumPy 创建区间数组:[0 1 2 3 4 5 6 7 8 9]
返回浮点型的,也可以指定类型
# 返回浮点型的,也可以指定类型
array14 = np.arange(5,dtype=float)
print(f"返回浮点型的,也可以指定类型:{array14}")
# 输出:返回浮点型的,也可以指定类型:[0. 1. 2. 3. 4.]
设置了起始值、终止值及步长:(步长也可以指定传参)
# 设置了起始值、终止值及步长:
array15 = np.arange(10,20,2)
print(f"设置了起始值、终止值及步长:{array15}")
# 输出:设置了起始值、终止值及步长:[10 12 14 16 18]
NumPy 创建等差数列
np.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype=None)
参数:
start:序列的起始值
stop:序列的终止值,如果endpoint为true,该值包含于数列中
num:要生成的等步长的样本数量,默认为50
endpoint:该值为 true 时,数列中包含stop值,反之不包含,默认是True
retstep:如果为 True 时,生成的数组中会显示间距,反之不显示
dtype:ndarray 的数据类型
#NumPy 创建等差数列
array16 = np.linspace(1,10,10)
print(array16)
参数endpoint 默认为True,包含stop值
# 参数endpoint 默认为True,包含stop值
array17 = np.linspace(1.0,3.0,num=5)
print(array17)
想得到一个长度为10的、从0.1开始的、间隔为0.1的数组
# 想得到一个长度为10的、从0.1开始的、间隔为0.1的数组
array18 = np.linspace(0.1,1,10)
print(array18)
NumPy创建等比数列
np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
参数:
start:序列的起始值
stop:序列的终止值,如果endpoint为true,该值包含于数列中
num:要生成的等步长的样本数量,默认为50
endpoint:该值为 true 时,数列中包含stop值,反之不包含,默认是True
base:对数 log 的底数
dtype:ndarray 的数据类型
#NumPy 创建等比数列
array19 = np.logspace(0,9,10,base=2)
print(array19)
NumPy创建全0数列:初始化矩阵
numpy.zeros(shape, dtype = float, order = ‘C’)
参数:
shape:数组形状
dtypr:ndarray的数据类型
# 全0数列:
array20 = np.zeros(5)
print(f"创建一个全为0的数组:{array20}")
# 更改数据类型
array21 = np.zeros(5,dtype='int')
print(f"数据类型更改为整型{array21}")
# 2行2列的全0数组
array22 = np.zeros((2,2))
print(f"2行2列的全0数组:{array22}")
# 2块2行3列的全0数组
array23 = np.zeros((2,2,3))
print(f"2块2行3列的全0数组:{array23}")
# zeros_like返回给定数组相同形状的全0数组
array24 = np.zeros_like([[1,2,3],[2,3,4],[5,6,7],[8,9,10]])
print(f"zeros_like返回给定数组相同形状的全0数组:{array24}")
// 输出:
//2行2列的全0数组:[[0. 0.]
//[0. 0.]]
//2块2行3列的全0数组:[[[0. 0. 0.]
//[0. 0. 0.]]
//[[0. 0. 0.]
///[0. 0. 0.]]]
//zeros_like返回给定数组相同形状的全0数组:[[0 0 0]
//[0 0 0]
//[0 0 0]
//[0 0 0]]
NumPy 创建全1数列:初始化矩阵
numpy.ones(shape, dtype = None, order = ‘C’)
参数:
shape:数组形状
dtypr:ndarray的数据类型
# NumPy 创建全1数列:初始化矩阵
array25 = np.ones(9)
print(f"创建全1数列:{array25}")
# ones_like返回给定数组相同形状的全1数组
array26 = np.ones_like([[1,2,3],[4,5,6]])
print(f"ones_like返回给定数组相同形状的全1数组:{array26}")
//输出:
//创建全1数列:[1. 1. 1. 1. 1. 1. 1. 1. 1.]
//ones_like返回给定数组相同形状的全1数组:[[1 1 1]
//[1 1 1]]
NumPy数组属性
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
# NumPy数组属性
print(f"返回数组的形状{array26.shape}")
print(f"返回数组的秩或者维度:{array26.ndim}")
print(f"数组元素的总个数:{array26}")
print(f"返回数组元素的类型:{array26.dtype}")
print(f"返回每个元素的大小:{array26.itemsize}")
输出
//返回数组的形状(2, 3)
//返回数组的秩或者维度:2
//数组元素的总个数:[[1 1 1]
//[1 1 1]]
//返回数组元素的类型:int32
//返回每个元素的大小:4
调整维度 reshape
返回调整维度后的副本,而不改变原 ndarray
# 调整维度 reshape
array27 = np.array([1,2,3,4,5,6])
array28 = array27.reshape((2,3))
print(f"28的形状:{array28.shape}")
print(f"27的形状:{array27.shape}")
// 输出
//28的形状:(2, 3)
//27的形状:(6,)
调整维度 resize
numpy.resize(原数组, 新数组的形状)
如果新数组大于原始数组,则新数组将填充a的重复副本。(顺时针)
# 调整维度 resize
array29 = np.array([
[0,1],
[2,3]
])
array30 = np.resize(array29,(2,3))
print(f"创建的新数组:{array30}")
方法astype()
numpy数据类型转换,调用astype返回数据类型修改后的数据,但是源数据的类型不会变
NumPy切片和索引
lndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。
# NumPy切片和索引
array31 = np.arange(10)
print(array31)
print(array31[2])
// 输出
//[0 1 2 3 4 5 6 7 8 9]
//2
# 索引从2开始到索引7停止,间隔为2
array32 = array31[2:7:2]
print(array32)
//输出
//[2 4 6]
如 [2],将返回与该索引相对应的单个元素
如果为 [2:],表示从该索引开始以后的所有项都将被提取
如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项
# 相当于倒去数组
print(f"取所有的数据,步长为-1:{array31[::-1]}")
# 定义4行5列的数据
array33 = np.arange(20).reshape(4,5)
print(f"定义4行5列的数据:{array33}")
print(f"返回第3行第3列的那个数:{array33[2][2]}")
print(f"返回第3行之后的所有数:{array33[2:]}")
print(f"返回所有行的第1列数:{array33[:][0]}")
// 输出
//定义4行5列的数据:[[ 0 1 2 3 4]
// [ 5 6 7 8 9]
// [10 11 12 13 14]
// [15 16 17 18 19]]
//返回第3行第3列的那个数:12
//返回第3行之后的所有数:[[10 11 12 13 14]
// [15 16 17 18 19]]
//返回所有行的第1列数:[0 1 2 3 4]
切片还可以使用省略号“…”,如果在行位置使用省略号,那么返回值将包含所有行元素,反之,则包含所有列元素
# 切片还可以使用省略号“…”,如果在行位置使用省略号,那么返回值将包含所有行元素,反之,则包含所有列元素
print(f"取第2列的数据{array33[...,1]}")
print(f"返回第2列的所有项:{array33[...,1:]}")
// 输出
//取第2列的数据[ 1 6 11 16]
//返回第2列的所有项:[[ 1 2 3 4]
// [ 6 7 8 9]
// [11 12 13 14]
// [16 17 18 19]]
索引的高级操作
# 索引的高级操作
array34 = np.arange(12).reshape(4,3)
print(array34)
print("=================")
# (0,0) (0,2) (3,0) (3,2)
array35 = array34[[0,0,3,3],[0,2,0,2]]
print(array35)
# 布尔索引
print(f"数组形状{array34.shape}")
print(f"返回数组中大于6的数据{array34[array34>6]}")
# 筛选
print(f"筛选区间大于4并且小于7的数据:{array34[(array34 > 4) & (array34 < 7)]}")
print(f"筛选大于4或者小于9的数据:{array34[(array34 > 4) | (array34 < 9)]}")
//输出
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
=================
[ 0 2 9 11]
数组形状(4, 3)
返回数组中大于6的数据[ 7 8 9 10 11]
筛选区间大于4并且小于7的数据:[5 6]
筛选大于4或者小于9的数据:[ 0 1 2 3 4 5 6 7 8 9 10 11]
广播机制
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行
如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape
那么 a*b 的结果就是 a 与 b 数组对应位相乘
这要求维数相同,且各维度的长度相同
# 广播机制
array36 = np.arange(12).reshape(4,3)
print(array36)
print("================")
array37 = np.arange(3).reshape(1,3)
print(array37)
print("================")
print(array36 + array37)
// 输出
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
================
[[0 1 2]]
================
[[ 0 2 4]
[ 3 5 7]
[ 6 8 10]
[ 9 11 13]]
数组37与数组36的形状不一样,37将形状通过复制第一行而补齐于36形状相同,在进行相加;
array38 = np.arange(3).reshape((3,1))
print(array38)
print("=============")
array39 = np.arange(3)
print(array39)
print("=============")
print(array38+array39)
// 输出
[[0]
[1]
[2]]
=============
[0 1 2]
=============
[[0 1 2]
[1 2 3]
[2 3 4]]
数组38补齐[[0 0 0]
[1 1 1]
[2 2 2]]
数组39补齐[[0 1 2]
[0 1 2]
[0 1 2]]
在相互相加