Numpy基础用法
一、创建数组
1. 从列表创建数组
创建一维数组
输入一个一维列表即可
arr_list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x1 = np.array(arr_list1)
创建二维数组
输入一个二维列表
注意二维列表的输入方式,使用
[arr_list1, arr_list2]
,参数为一个二维列表,不是2个参数dtype:指定元素数据类型
arr_list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
arr_list2 = [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
x1 = np.array([arr_list1, arr_list2], dtype=int)
2. 从头创建数组
- np.zeros:生成一个填充0的数组,生成一个3×4,填充0的二维数组
- np.ones:生成一个填充1的数组,生成一个2×4,填充1的二维数组
- np.full:生成一个指定内容的数组,生成一个3×5,填充9.9的二维数组
x2 = np.zeros((3, 4), dtype=float)
x2 = np.ones((2, 4), dtype=int)
x2 = np.full((3, 5), 9.9, dtype=float)
3. 创建序列数组
- np.arange:简单序列数组,默认的step为1,从1开始,小于10(不包含10),步长为2
- np.linspace:等差数组,
- np.logspace:等比数组
- np.random.randint:随机数组,在1-10之间随机生成一个3×4的数组
x3 = np.arange(1, 10, 2, dtype=int)
# 等差数列
x3 = np.linspace(1, 100, 100, dtype=int)
# 等比数列
x3 = np.logspace(1, 100, 50)
# 随机
x3 = np.random.random((3, 3))
x3 = np.random.randint(1, 10, (3, 4))
二、数组的性质
- shape:数组的形状,即含有几行×几列
- ndim:数组的维度,如:二维,一维
- dtype:数组的元素数据类型
x4 = np.random.randint(1, 50, (5, 8))
print('x4数组的形状', x4.shape)
print('x4数组的维度', x4.ndim)
print('x4数组的类型', x4.dtype)
三、数组的索引
- x5[1]:获取一行
- x5[:, 1]:获取一列
x5[1][2]
:获取第1行第2列元素x5[1, 2]
:同上,两种写法都可以
x5 = np.random.randint(1, 40, (6, 7))
print('x5二维数组获取一行', x5[1])
print('x5二维数组获取一列', x5[:, 1])
print('x5指定位置:', x5[1][2])
print('x5指定位置:', x5[1, 2])
四、数组的切片
1. 一维数组切片
- x6[5:12]:选取5~11元素,不包含尾部(12),同列表的使用相同;
- x6[::-1]:反向输出(逆序输出),同列表使用相同;
- x6[:-2]:输出0至第三个元素
x6 = np.random.randint(1, 30, 15)
# 包含起点,不包含终点
print('截取一段', x6[5:12])
print('截取至倒数第三个元素', x6[:-2])
# 注意是2个:
print('反向输出', x6[::-1])
2. 二维数组切片
- x6[:2, :3]:0-1行×0-2列
- x6[::-1,::-1]:反向输出(先按行反向,然后再按列反向),与矩阵的转置不同
- x6[:1,0:5:3]:第一个参数是行,第二个参数是列(3表示步长)。即第
- x6[1,:]:获取第一行,与x6[1]相同
- x6[:,2]:获取第二列,注意观察与获取行的区别。
print('截取一段', x6[:2, :3])
# 可以理解为先按行反向,然后再按列反向(与转置是不同的)
print('反向输出',x6[::-1,::-1])
# 3为步长
print(x6[:1,0:5:3])
# 也可以写为:x6[1]
print("获取一行:",x6[1,:])
print('获取一列:',x6[:,2])
3. 视图与拷贝区别
视图获取的仍然是原数组的内容,修改的仍然是原数组
拷贝则另外生成一个新的数组,与原数组不同
x7[0,0]=35
:修改原数组,属于视图模式x7=x6[:2,:3].copy()
:生成一个新的数组,对元素的改变不影响原数组
x7=x6[:2,:2]
x7[0,0]=35
# 使用copy方法,返回副本,不影响原数组
x7=x6[:2,:3].copy()
x7[0,0]=38
五、数组的变形
1. 一维数组变二维数组
- reshape:将一维数组重构为二维数组:
x8=x7.reshape(3,4)
,np.random.randint(1,20,(12,))
,生成一维数组x8[1,1]=100
*:修改数组内容,reshape,获得的是视图,不是副本,因此修改的是原数组。
# 注意写法:(12,)表明是一个一维数组;(12,1)是一个2维数组,12×1
x7=np.random.randint(1,20,(12,))
print(x7.shape)
# 维度转换,必须元素的长度是一致的。1×23=3×4
x8=x7.reshape(3,4)
# reshap生成的是视图,修改数组内容,影响原数组
x8[1,1]=100
2. 二维数组变一维数组
- flatten():二维数组变一维数组,返回的是拷贝(副本);
- ravel():二维数组变一维数组,返回的是视图;
- reshape(-1):二维数组变一维数组,返回的是视图;
x7=np.random.randint(1,30,(3,4))
# flatten:返回副本
x8=x7.flatten()
# ravel:返回视图
x9=x7.ravel()
# reshape:返回视图
x10=x7.reshape(-1)
六、数组拼接
hstack和vstack两种拼接方法,均返回的是副本,即生成一个新的数组。
1. 水平拼接
注意参数的写法,传入的是一个数组(包含2个数组),且两种写法功能相同
- np.hstack([x8,x9]):
- np.c_[x8,x9]:
x8=np.random.randint(1,20,(2,3))
x9=np.random.randint(30,50,(2,3))
# 水平拼接,np.hstack
# 注意参数写法[arr1,arr2]
x10=np.hstack([x8,x9])
print(x10)
# 水平拼接,np.c_
# 注意参数写法
x11=np.c_[x8,x9]
print(x11)
2. 垂直拼接
使用方式与水平拼接相同
- np.vstack([x8,x9]):
- np.r_[x8,x9]:
x8=np.random.randint(1,20,(2,3))
x9=np.random.randint(30,50,(2,3))
x12=np.vstack([x8,x9])
print(x12)
x13=np.r_[x8,x9]
print(x13)
七、数组分裂
1. 一维数组分裂
np.split(x9,[5,12])
:
- 第一个参数:被分裂的数组;
- 第二个参数:分裂的位置(传入的是一个数组),出入数组参数为下一个数组的起点;
- [5,12]:分裂为3个数组,0~4,5~11,12~19
x9=np.random.randint(1,30,20)
# 不包含终点,即可以理解为下一个的起点
# 注意索引参数的用法[]
x10,x11,x12=np.split(x9,[5,12])
print(x10,x11,x12)
2. 二维数组分裂
- 按行分裂
np.vsplit(x10,[2,3])
:垂直(纵向)方向分裂,[2,3]表示:按第0~1行,第2行,第3行共三个数组- 按列分裂
np.hsplit(x10,[2,3])
:水平(横向)方向分裂,[2,3]表示,按第0~1行,第2行,第3~4行共三个数组
x10=x9.reshape(4,5)
# 按行分裂
# 注split和vsplit相同
x11,x12,x13=np.vsplit(x10,[2,3])
print(x11,'\n',x12,'\n',x13)
# 按列分裂
x11,x12,x13=np.hsplit(x10,[2,3])
print(x11, '\n', x12, '\n', x13)
八、数组运算
1. 向量化运算
数组内部元素逐个参与运算,如+,-,×,/,以及各类内部函数的计算,返回仍然是一个大小(shape)相同的数组
x10=np.arange(1,10)
x11=np.arange(11,20)
# 内部元素对应位置的+,-,×,/
print(x10+5)
print(x10+x11)
print(x10*x11)
# numpy内部函数:sin,cos,tan,log,log2,log10等,返回一个数组。
print(np.sin(x10))
print(np.log(x11))
2. 矩阵运算
主要包含两种运算:
- 转置:根据对角线互相交换位置,如索引
[0,1]
换到[1,0]
,这里与二维数组的行和列均反向输出是不同的。- 乘法:矩阵的乘法,注意区分向量的乘法,且
x10.dot(x11)
和np.dot(x10,x11)
功能相同
x10=np.arange(1,10).reshape(3,3)
x11=np.arange(11,20).reshape(3,3)
# 矩阵转置
print(x10.T)
# 矩阵乘法
print(x10.dot(x11))
print(np.dot(x10,x11))
3. 比较运算
x10>50
:判断数组大于50的元素,大于50返回True,否则返回False,返回的是一个大小(shape)相同的数组,内部根据元素填充True和Falsenp.sum(x10>50)
:统计大于50元素的个数np.sum((x10 > 50) & (x10 < 80))
:多个条件统计,统计大于50,且小于80元素的个数np.all(x10>0)
:判断数组元素是否均大于0np.all(x10>50,axis=1)
:按行判断元素是否大于50,根据行数返回一个填充True和False的数组。axis=1
轴向,1表示按行,0表示按列
x10=np.random.randint(1,100,(10,10))
# 返回一个10×10数组,填充false、ture,大于50为true,其他填充为false
print(x10>50)
# 统计大于50的个数
print(np.sum(x10>50))
# 多条件判断50< <80
print(np.sum((x10 > 50) & (x10 < 80)))
# 判断元素是否全部大于0
print(np.all(x10>0))
# 判断按行是否全部大于50;axis为轴,1行,0列
print(np.all(x10>50,axis=1))
4. 掩码运算
结合比较运算,根据比较运算生成的True和False数组,获取原数组为True的元素。
x10=np.random.randint(1,100,(10,10))
# 掩码运算:获取大于50的元素
# x10>50返回false,true数组
# x10[]从数组中获取为True的元素
print(x10[x10>50])
九、加强版索引
通过数组形式的索引,获取原数组的元素
1. 一维数组
- 索引是一个数组,如:
ind=[1,5,9]
,然后通过索引数组获取原数组的元素,x11[ind]
- 同样可以构建一个二维索引数组,如:
ind=[[2,4],[3,1]]
,然后通过索引数组获取数组的元素构建一个二维数组,x11[ind]
x11=np.random.randint(1,100,10)
# 定义一个索引数组
ind=[1,5,9]
# 根据索引数组,返回数组内容
print(x11[ind])
# 根据索引,生成二维数组
ind=[[2,4],[3,1]]
print(x11[ind])
2. 二维数组
- 构建2个数组索引,分别对应行和列;
- 然后通过数组索引获取原二维数组的元素
x11 = np.random.randint(1, 100, (5, 5))
print(x11)
# 定义行、列索引
row=np.array([0,2,4])
col=np.array([1,3,0])
x12=x11[row,col]
十、其他函数
Numpy的功能更加强大,已经内置很多函数,如极值、求和、求积、均值等。
1. 一维数组
- np.sort:数组排序,原数组不变,生成一个新数组;
- x12.sort():数组排序,对原数组进行操作
- np.max:求数组最大值
- np.min:求数组最小值
- np.argmax:获取数组最大值的索引
- np.argmin:获取数组最小值的索引
- np.sum:数组求和
- x12.sum:数组求和,功能同上
- np.prod:数组求积
- x12.prod:数组求积
x12=np.random.randint(1,100,15)
# np.sort排序,原数组不变,生成一个新数组
print(np.sort(x12))
print(x12)
# 替换原数组,为生成排序变化后的数组
x12.sort()
print(x12)
# 最大、小值元素
print(np.max(x12),np.min(x12))
# 最大、小值元素的索引
print(np.argmax(x12),np.argmin(x12))
print(np.sum(x12))
2. 二维数组
- np.sum(x12,axis=1):axis按行或列求和
x12=np.random.randint(1,100,(4,4))
print(x12)
print(np.sum(x12))
# 按行求和,轴=1
print(np.sum(x12,axis=1))
~