numpy介绍
1.概述
NumPy是一个Python库,用于数值计算和处理数组。它是其他数据分析和机器学习库的底层库,提供了高效的多维数组运算功能。NumPy完全使用标准C语言实现,以提高运行效率。它是一款开源免费的库。并于1995年由Numeric项目发展而来。在2001年,Numpy被集成到Scipy库中,并进一步扩展了多维数组和矩阵运算的功能。
numpy的核心:多维数组+数值计算
1.代码简洁减少Python代码中的循环。
2.底层实现:厚内核(C)+薄接口(Python),保证性能。
2. numpy基础
内存中的ndarray对象由两个部分组成,一部分是元数据,是实际的数组数据,它是一个同质数组,即所有元素的数据类型必须相同。另外一部分是元数据,元数据存储对目标数组的描述信息,如:ndim、dimensions、dtype、data等。实际数据将与元数据分开存放,一方面提高了内存空间的使用效率,另一方面减少了对实际数据的访问频率,提高了性能。
3.列表转numpy数组
import numpy as np ary=np.array([1,2,3,4,5,6])#列表转数组,如果不指定dtype,则默认是int32 print(ary)#[1 2 3 4 5 6]元素与元素之间为空格 print(type(ary))#<class 'numpy.ndarray'>
注意,numpy数组的元素与元素之间没有,而是空格,这一点与python的列表不同。
4. numpy数组的广播机制
import numpy as np #广播机制:数组与一个元素进行计算时,数组中的每一个元素分别进行计算 ary=np.array([1,2,3,4,5,6])#列表转数组 print(ary+3)#[4 5 6 7 8 9] print(ary*2)#[ 1 4 9 16 25 36] print(ary==3)#[False False True False False False] print(ary+ary)#[ 2 4 6 8 10 12] print(ary * ary)#[ 1 4 9 16 25 36]
注意,在python的列表中是没有广播的。
5. numpy常用函数
常用函数包括array、arange、zeros、ones、zeros_like、ones_like、linspace、astype等。看下面的简单例子。
''' ndarray数组的基本创建及特点 ''' import numpy as np
a=np.arange(0,5,1)#[0 1 2 3 4] #python中的range只能生成整数,不能生成小数,但是np.arange可以生成小数 b=np.arange(0.1,1.1,0.2) print(b)#[0.1 0.3 0.5 0.7 0.9] c=np.zeros(10,dtype='int32')#如果不指定数据类型,默认是小数 print(c)#[0 0 0 0 0 0 0 0 0 0] c=np.zeros(shape=(10,),dtype='int32') print(c) zeros=np.zeros(shape=(2,3),dtype="int8") print(zeros) ones=np.ones(shape=(2,3),dtype="int32") print(ones) #np.zeros_like() ary=np.arange(0,10).reshape(2,5) zeros_like=np.zeros_like(ary) print(zeros_like)#[[0 0 0 0 0][0 0 0 0 0]] ones_like=np.ones_like(ary) print(ones_like)#[[1 1 1 1 1] [1 1 1 1 1]] #生成值全为0.2的数组 r=np.zeros(shape=(10,))+0.2 print(r)#[0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2] #生成-3.14到3.14中的6个数 pai=np.arange(-3.14,3.14,6.18/5) print(pai) #np.linspace(start,stop,个数)#闭区间[] #生成-3.14到3.14中的5个数 pai=np.linspace(-3.14,3.14,5) print(pai)#[-3.14 -1.57 0. 1.57 3.14]
6. numpy数组对象的基本属性
numpy数组对象常用的属性包括shape、dtype、size等。
import numpy as np ary=np.arange(1,11)#[ 1 2 3 4 5 6 7 8 9 10] print(ary.shape)#(10,) #将一维数据变为二维数据 ary.shape=(2,5) print(ary) ary.shape=(1,2,5) print(ary) ary.shape=(2,1,5) print(ary) #dtype ary=np.arange(1,9) print(ary) print(ary.dtype)#int32 #修改元素数据类型不能直接给dtype赋值 # ary.dtype='float32'#这里表示用float32解析 # print(ary)#[1.4e-45 2.8e-45 4.2e-45 5.6e-45 7.0e-45 8.4e-45 9.8e-45 1.1e-44] #astype函数 bry=ary.astype('float64')#不会改边原始数据类型 print(ary)#不变[1 2 3 4 5 6 7 8] print(bry)#[1. 2. 3. 4. 5. 6. 7. 8.] #数组元素的个数 #np.array.size ary=np.arange(1,9) print(ary.size)#8 print(len(ary))#8,最表层的元素个数 ary.shape=(2,4) print(ary.size)#8 print(len(ary))#2
7. 数组元素索引
#数组元素索引(下标) #index ary=np.arange(1,9) ary.shape=(2,2,2) print(ary[0]) print(ary[0][0])#[1 2] print(ary[0][0][0])#1 #另外一种方式索引 print(ary[0,0])#[1 2] print(ary[0,0,0])#1
有两种方式,一种是arr[x][y],还有一种是arr[x,y]。
8. numpy内部基本数据类型
内部基本数据类型包括int、float、str等数据类型。
- int: int8、int16、int32、int64 、uint8(代表无符号)
- float: float16、float32、float64
- str字符串类型
- int8 表示2**8个数字即 -128到127 有符号
- uint8表示256个数字 无符号即只有正数 即0到255
-
complex64 complex128 复数型
import numpy as np #bool_(bool也可以) ary=np.ones(shape=(2,2),dtype='bool_') print(ary)#[[ True True] [ True True]] ary=np.ones(shape=(2,2),dtype='bool') print(ary)#[[ True True][ True True]] #bool可以简写?,后面会再提到 ary=np.ones(shape=(2,2),dtype='?') print(ary) ary=np.array([1,2,3],dtype='int32') print(ary) #str_类型,每个字符32位,4个字节 #str缩写大写U,表示unicdoe #为了方便定位,numpy规定每个元素占据的字节数相等 ary=np.array(['a','bc','def']) print(ary.dtype)#<U3,小于表示小端存储,U3表示unicode,3个字符 print(ary.nbytes)#36字节数 -->3*4(一个字符4个字节)*3(元素个数) 输出占据多少个字节 print(ary.itemsize)#12,最长的字符串字节数 #datetime64日期类型 #'2023-08-16 15:23:22' str #需要转换为datetime64数据类型,再转换为int64 data=np.array(['2021','2022-01-01','2023-01-01 08:08:08']) print(data) print(data.dtype)#<U19 dates=data.astype('datetime64')#会自动补充,精度最高的一个元素为准 print(dates) dates=data.astype('datetime64[D]')#YMDhms 年月日时分秒 datetime64[D]表示精确到天 print(dates) res=dates.astype('int64')#时间日期类型转整数int64 print(res)#[18628 18993 19358]#距离1970年1月1日的天数 dates=data.astype('datetime64[s]')#YMDhms 年月日时分秒 datetime64[D]表示精确到天 print(dates) res=dates.astype('int64')#时间日期类型转整数int64 print(res)#[1609459200 1640995200 1672560488]距离1970年1月1日:00:00:00的秒数
9. 自定义复合类型
对于较新版本的numpy,同一列的数据类型需要保持相同,列同质,同一行内的可以不同,也就是行可以不同质,但会出现警告。
import numpy as np data=[('zs',[90,80,85],15), ('zf',[80,90,70],20), ('wx',[70,90,80],20) ] ary=np.array(data) print(ary) """ [['zs' list([90, 80, 85]) 15] ['zf' list([80, 90, 70]) 20] ['wx' list([70, 90, 80]) 20]] """ ary=np.array(data,dtype='U2,3int32,int32')#后面会提到 print(ary) ''' [('zs', [90, 80, 85], 15) ('zf', [80, 90, 70], 20) ('wx', [70, 90, 80], 20)] ''' total_age=0.0 for i in data: total_age+=i[2] print(total_age/3)#求平均年龄
10. 访问列数据
下面这个例子,f表示列,f2表示第3列。
#访问列数据 print(ary['f2'])#第3列数据,[15 20 20] print(ary['f1']) print(type(ary['f1']))#<class 'numpy.ndarray'>
11. 类型字符码
这部分内容了解即可,数据类型int8可以用i1代替(8表示一个字节,8位,所以为i1),float64就是f8.
12. numpy数组变维
12.1 视图变维
视图变维不会修改原始数据的维度,但是两者的数据是共享的(更改一个数据,另一个会变化)下面的例子中ravel()函数用于将多维数组展平为一维数组。reshape(参数)可以将数组维度重新设置,但是数据是共享的。
#视图变维:不会修改原始数据的维度,数据共享 ary=np.arange(1,10) print(ary)#[1 2 3 4 5 6 7 8 9] bry=ary.reshape(3,3) print(ary)#[1 2 3 4 5 6 7 8 9]#ary的维度并没有改变 print(bry)# #修改ary中的元素 ary[0]=666 print(ary)#[666 2 3 4 5 6 7 8 9] print(bry)#[[666 2 3][ 4 5 6][ 7 8 9]] ary=np.arange(1,10).reshape(3,3) print(ary)
12.2 复制变维
import numpy as np # 复制变维 不会修改原始数据的维度,数据独立 ary=np.arange(1,9).reshape(2,2,2) bry=ary.flatten() print(ary)#[[[1 2][3 4]] [[5 6][7 8]]] print(bry)#[1 2 3 4 5 6 7 8] bry[0]=-1 print(bry)#[-1 2 3 4 5 6 7 8] print(ary)#没有-出现1,其数据与bry数据是互不影响的
12.3 就地变维
就地变维:就地改变原数组,不返回新数组
import numpy as np ary=np.arange(1,19)#1~18 ary.resize(2,3,3) print(ary.shape)#(2, 3, 3)
13. numpy数组切片
直接看下面的例子:
import numpy as np a=np.arange(1,10) print(a[:3])#[1 2 3] print(a[-4:-7:-1]) ''' 数组的切片 注意:切片不会降维,索引会降维(一个索引降一个维) ''' ary=np.arange(1,19).reshape(2,9) print(ary) #三维数组[行的操作,列的操作] #第0行的前两列print(ary[:1,:2])#[[1 2]] print(ary[0,:2])#[1 2] ary=np.arange(1,51).reshape(5,10) print(ary) #拿到所有行,不要最后一列(二维) print("拿到所有行,不要最后一列(二维)") print(ary[:, :-1]) #拿到所有行,只要最后一列(一维) print("拿到所有行,只要最后一列(一维)") print(ary[:,-1])
14. numpy数组掩码操作
14.1 布尔掩码
import numpy as np ary=np.array([1,2,3,4,5,6,7,8,9]) mask=[True,False,True,True,False,True,False,True,True]#mask既可以是数组也可以是列表 print(ary[mask])#[1 3 4 6 8 9] #求1,100以内3的倍数 ary=np.arange(1,101) mask=[False,False,True]*33+[False] print(ary[mask]) mask=ary%3==0 print(ary[mask]) #求1,100以内能够同时被3和7整取的数字 ary=np.arange(1,101) # mask=ary%3==0 and ary%7==0#会报错,numpy不支持and操作,因为其是C语言写的 mask=(ary%3==0) & (ary%7==0) print(mask) print(ary[mask])#[21 42 63 84]
布尔掩码的元素个数要与被操作的numpy数组元素个数相等,布尔值为True的对应的位置的元素会被保留下来。
14.2 索引掩码
不解释了,关于用法直接看例子。
import numpy as np #索引掩码 #索引掩码个数不需要一定与原数组元素个数相等 car=np.array(['BMW','Benz','Audi','BYD','Tesla']) mask=[3,4,1,0,2]#['BYD' 'Tesla' 'Benz' 'BMW' 'Audi'] print(car[mask]) mask=[3,4]# print(car[mask])#['BYD' 'Tesla'] mask=[3,4,3,4,3,3]#可以重复 print(car[mask])#['BYD' 'Tesla' 'BYD' 'Tesla' 'BYD' 'BYD']
索引掩码个数不需要一定与原数组元素个数相等。
''' 多维数组组合与拆分 ''' import numpy as np x=np.arange(1,7).reshape(2,3) y=np.arange(7,13).reshape(2,3) #垂直:v res=np.vstack((x,y))#[[ 1 2 3][ 4 5 6][ 7 8 9][10 11 12]] print(res) x,y=np.vsplit(res,2) print(x)#[[1 2 3][4 5 6]] print(y)#[[ 7 8 9][10 11 12]] #水平:h res=np.hstack((x,y))#[[ 1 2 3 7 8 9][ 4 5 6 10 11 12]] print(res) x,y=np.hsplit(res,2)#[[1 2 3][4 5 6]] print(x) print(y)#[[ 7 8 9][10 11 12]] #深度:d res=np.dstack((x,y))#[[[ 1 7][ 2 8][ 3 9]][[ 4 10][ 5 11][ 6 12]]] print(res) x,y=np.dsplit(res,2) print(x)#[[[1][2][3]][[4][5][6]]] print(y)#[[[ 7][ 8][ 9]][[10][11][12]]] #np.concatenate((a,b),axis=0) #axis值:0垂直,1水平,2深度
三维数组组合分为三个方向,分别是垂直,水平,深度。也可以使用np.concatenate((a,b),axis=)根据axis组合数组。
总结:关于reshape函数,如果想要设置m行,列数由数据总数/m确定,可以设置为-1.如reshape(m,-1)。注意,关于数组切片,切片不会导致降维,而索引会导致降维。
参考资料:
https://blog.csdn.net/qq_53763141/article/details/128391160
http://www.taodudu.cc/news/show-4218173.html?action=onClick
https://zhuanlan.zhihu.com/p/478249595