Python数据分析之Numpy学习(一)一、Numpy的引入1.1矩阵/向量的按位运算需求:矩阵的按位相加[0,1,4]+[0,1,8]=[0,2,12]1.1.1利用python实现矩阵/向量的按位运算#1.通过列表实现list1=[0,1,4]list2=[0,1,8]123#列表使用+操作是将两个列表进行连接,不是算术运算list1+list2#结果:1234[0,1,4,0,1,8]1#使用循环+append实现list_sum=[]#通过索引进行遍历foriinrange(len(list1)):#通过索引同时遍历list1和list2,方便从2个列表中同时提取数据list_sum.append(list1[i]+list2[i])list_sum123456789[0,2,12]1#2.通过推导式实现[list1[i]+list2[i]foriinrange(len(list1))]12[0,2,12]1对上述的按位相加运算进行扩充:扩充到两个n位的列表进行按位相加操作,第一个列表的元素是0到n-1的平方,第二个列表的元素是0到n-1的三次方[0,1,4,…]+[0,1,8,…]=[0,2,12,…]#构建一个函数,用来生成0到n-1的m次方列表defcreate_list(n,m):#n是列表中的元素数量,m是所求次方return[item**mforiteminrange(n)]123#测试构建的函数#生成10个元素的平方create_list(10,2)123[0,1,4,9,16,25,36,49,64,81]1#生成5个元素的立方create_list(5,3)12[0,1,8,27,64]1#构建函数用来实现n个元素的平方和立方的按位相加defpySum(n):#n是列表的元素数量list_1=create_list(n,2)list_2=create_list(n,3)return[list_1[i]+list_2[i]foriinrange(n)]12345#测试Pysum函数pySum(5)12[0,2,12,36,80]1pySum(10)1[0,2,12,36,80,150,252,392,576,810]11.1.2用numpy实现矩阵/向量的按位运算#载入库importnumpyasnp12#构建用Numpy实现按位相加的函数defnpSum(n):a=np.arange(n)**2b=np.arange(n)**3returna+b12345#测试npSum函数npSum(5)12array([0,2,12,36,80])1npSum(10)1array([0,2,12,36,80,150,252,392,576,810])11.1.3numpy与原生python在科学计算上的对比#(1)溢出的问题#python实现,正常pySum(100000)[-3:]123[999920002099982,999950000799996,999980000100000]1#numpy实现,出现了溢出问题npSum(100000)[-3:]12array([75983630,9912572,-55558496])1在Windows操作系统下,用numpy创建的整数类型的数组默认采用的是np.int32数据类型,该数据类型能容纳的最大数值是2^31-1,当我们要计算的数值超过该数值,计算结果就会出错,解决方法是采用更大的数据类型np.int64。#修改按位相加函数中的数组的数据类型改为np.int64defnpSum64(n):a=np.arange(n,dtype=np.int64)**2b=np.arange(n,dtype=np.int64)**3returna+b12345#测试npSum64函数是否还会出现溢出问题,结果是输出正确结果npSum64(100000)[-3:]12array([999920002099982,999950000799996,999980000100000],dtype=int64)1#(2)代码简洁程度:numpy代码比python代码实现按位相加要更简洁1#(3)numpy与原生python在科学计算上的性能差异#%timeit#精确计算其后代码执行的时间长度,是jupyter上的一个特殊的命令(魔法命令)%timeitpySum(100000)12336.4ms±922μsperloop(mean±std.dev.of7runs,10loopseach)1%timeitnpSum64(100000)11.03ms±11.6μsperloop(mean±std.dev.of7runs,1,000loopseach)1两者执行相差:35.7/1,相差三十多倍,随着计算的复杂程度的提高,numpy节约的时间越多总结:从上述情况来看,在实现科学计算上,不管是从代码的简洁程度还是执行效率上来看,numpy的表现较好1.2Numpy的简介NumPy是一个开源的Python科学计算库,它包括:一个强大的N维数组对象ndrray;比较成熟的函数库;用于整合C/C++和Fortran代码的工具包;实用的线性代数、傅里叶变换和随机数生成函数NumPy支持高维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。Numpy成为事实上的Scipy、Pandas、Scikit-Learn、Tensorflow、PaddlePaddle等框架的"通用底层语言"。Numpy的array和Python的List的一个区别,是它元素必须都是同一种数据类型,比如都是数字int类型,这也是Numpy高性能的一个原因。1.2.1Python的缺点和Numpy的改进标准Python中用列表(list)可以用来当作数组使用,但是列表中所保存的是对象(任意对象)的指针。对于数值运算来说这种结构比较浪费内存和CPU计算时间。NumPy提供了以下对象,解决标准Python的不足:①ndarray:N维数组(简称数组)对象,存储单一数据类型的N维数组②ufunc:通用函数对象,对数组进行处理的函数。1.2.2Ndarray的理解NumPy中的ndarray是一个多维数组对象,它是一个快速而灵活的大数据集容器,它由两部分组成:①实际的数据;②描述这些数据的元数据。(相当于形状)大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据。形状:描述数组的元数据二、创建Ndarray2.1一维数组的创建2.1.1np.array创建数组#?np.array1array(object,dtype=None,*,copy=True,order='K',subok=False,ndmin=0,like=None)object:用来转换为数组的对象,一般是容器/序列类对象dtype:数据类型,一般不专门设置,因为np会自动识别对象的数据类型注意:array是个函数,后面要写成()#1.列表转数组arr1=np.array([1,2,3,4,5])arr1#直接写是访问对象,直接访问对象是用逗号隔开123array([1,2,3,4,5])1#用print输出,输出结果用空格隔开print(arr1)12[12345]1列表直接访问和用print输出没有区别,都是用逗号隔开,但是数组不一样#观察arr1的数据类型type(arr1)#numpy.ndarray12numpy.ndarray1#2.元组转数组np.array((1,2,3))12array([1,2,3])1#3.range转数组np.array(range(10))12array([0,1,2,3,4,5,6,7,8,9])1#4.字符串转数组,得到的不是字符,而是一个完整的字符串np.array('hello')12array('hello',dtype=',order='C',*,like=None))(1)N,M:行列的元素数量(2)k:对角线的位置,该值为正,对角线向右移动,该值为负,对角线的位置向左移动(3)dtype:数据类型,默认是浮点型,可以根据需求进行指定#?np.eye1#行列数一致时np.eye(7)12array([[1.,0.,0.,0.,0.,0.,0.],[0.,1.,0.,0.,0.,0.,0.],[0.,0.,1.,0.,0.,0.,0.],[0.,0.,0.,1.,0.,0.,0.],[0.,0.,0.,0.,1.,0.,0.],[0.,0.,0.,0.,0.,1.,0.],[0.,0.,0.,0.,0.,0.,1.]])1234567#行列数不一致时np.eye(3,5)12array([[1.,0.,0.,0.,0.],[0.,1.,0.,0.,0.],[0.,0.,1.,0.,0.]])123#对角线的移动np.eye(7,k=2)12array([[0.,0.,1.,0.,0.,0.,0.],[0.,0.,0.,1.,0.,0.,0.],[0.,0.,0.,0.,1.,0.,0.],[0.,0.,0.,0.,0.,1.,0.],[0.,0.,0.,0.,0.,0.,1.],[0.,0.,0.,0.,0.,0.,0.],[0.,0.,0.,0.,0.,0.,0.]])1234567np.eye(7,k=-2)1array([[0.,0.,0.,0.,0.,0.,0.],[0.,0.,0.,0.,0.,0.,0.],[1.,0.,0.,0.,0.,0.,0.],[0.,1.,0.,0.,0.,0.,0.],[0.,0.,1.,0.,0.,0.,0.],[0.,0.,0.,1.,0.,0.,0.],[0.,0.,0.,0.,1.,0.,0.]])1234567#更改数据类型np.eye(7,dtype=int)12array([[1,0,0,0,0,0,0],[0,1,0,0,0,0,0],[0,0,1,0,0,0,0],[0,0,0,1,0,0,0],[0,0,0,0,1,0,0],[0,0,0,0,0,1,0],[0,0,0,0,0,0,1]])12345672.3.3通过随机的方式创建数组2.3.3.1按照指定的分布特征构正态分布np.random.randn,语法:np.random.randn(d0,d1,...,dn)均匀分布np.random.rand范围是[0,1),语法:np.random.rand(d0,d1,...,dn)其中d0,d1,…,dn代表每个维度上的元素数量#创建一个均匀分布的随机数组,利用round控制小数位数np.random.rand(3,4).round(3)12array([[0.516,0.725,0.887,0.496],[0.592,0.773,0.192,0.284],[0.363,0.058,0.715,0.586]])123#如何查看它符合均匀分布,通过可视化进行观察a4=np.random.rand(10000)12importmatplotlib.pyplotasplt#绘制一个直方图,观察数据分布情况plt.hist(a4,bins=100)plt.show()1234#创建一个符合正态分布的数组a5=np.random.randn(10000)12#绘制一个直方图,观察数据分布情况plt.hist(a5,bins=100)plt.show()1232.3.3.2按照指定的数据范围np.random.randint生成指定范围的随机整数数组语法:np.random.randint(low,high=None,size=None,dtype=int)np.random.uniform生成指定范围的随机浮点数数组语法:np.random.uniform(low=0.0,high=1.0,size=None)low/high:数组元素的最小/最大值size:数组的形状返回的结果都是左闭右开的区间importrandom1#4名学生,5门功课的成绩(成绩在60~100分之间),要写101,因为右边是开区间a6=np.random.randint(60,101,size=(4,5),dtype=int)a6123array([[100,95,97,99,99],[67,61,89,93,63],[94,67,82,74,75],[96,84,76,64,71]])1234whileTrue:a=random.randint(60,100)print('随机值:',a)ifa==100:break12345随机值:87随机值:64随机值:65随机值:92随机值:61随机值:76随机值:96随机值:78随机值:97随机值:69随机值:60随机值:61随机值:10012345678910111213#生成5支股票7天的收盘价8~20之间np.random.uniform(8,20,(7,5)).round(2)12array([[10.44,11.39,12.04,12.69,11.47],[15.85,11.96,17.18,12.4,10.39],[11.42,8.42,16.64,19.38,9.54],[10.06,11.71,8.19,18.55,11.],[8.69,18.28,14.5,11.41,14.21],[9.79,11.8,11.41,10.37,17.61],[18.11,19.35,17.8,18.09,10.78]])1234567#randint生成方式np.random.randint(80,201,(7,5))/1012array([[11.3,14.8,12.1,13.7,8.3],[9.9,12.2,13.,13.6,10.6],[10.3,10.,20.,20.,8.7],[9.2,14.5,11.1,12.3,15.4],[15.3,15.7,15.3,9.5,12.2],[14.8,15.7,15.2,13.7,14.3],[8.5,13.3,11.2,9.,15.2]])12345672.4高维数组(三维及以上的维度)的创建2.3.1用占位方法创建数组#创建一个三层,三行,三列的全0数组a7=np.zeros((3,3,3))a7123array([[[0.,0.,0.],[0.,0.,0.],[0.,0.,0.]],[[0.,0.,0.],[0.,0.,0.],[0.,0.,0.]],[[0.,0.,0.],[0.,0.,0.],[0.,0.,0.]]])1234567891011a7.ndim131a7.shape1(3,3,3)12.3.2使用reshape方法创建数组2.3.2.1在数组上调用ndarray.reshape,语法:a.reshape(shape,order='C')shape:希望改变成的形状,如果是int,就是一维数组,如果是int的元组,就是多维数组#?np.ndarray.reshape1#创建一个5行6列,值是1~30的数组#(1)先创建一个1~30的一维数组a01=np.arange(1,31)a011234array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30])12#(2)针对创建的数组进行reshape操作a01_re=a01.reshape((5,6))a01_re123array([[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29,30]])12345a01_re.ndim121a01_re1=a01.reshape((3,2,5))a01_re112array([[[1,2,3,4,5],[6,7,8,9,10]],[[11,12,13,14,15],[16,17,18,19,20]],[[21,22,23,24,25],[26,27,28,29,30]]])12345678a01_re1.ndim1312.3.2.2在numpy上调用np.reshape,语法:np.reshape(a,newshape,order='C'),其中a是要改变的数组newshape:希望改变成的形状,如果是int,就是一维数组,如果是int的元组,就是多维数组#创建一个5行6列,值是1~30的数组np.reshape(np.arange(1,31),(5,6))12array([[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29,30]])12345np.reshape(np.arange(1,31),(5,3,2))1array([[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]],[[13,14],[15,16],[17,18]],[[19,20],[21,22],[23,24]],[[25,26],[27,28],[29,30]]])12345678910111213141516171819np.reshape(a01,(3,2,5))1array([[[1,2,3,4,5],[6,7,8,9,10]],[[11,12,13,14,15],[16,17,18,19,20]],[[21,22,23,24,25],[26,27,28,29,30]]])12345678注意:(1)使用reshape时,要注意转换前后数组的元素数量要保持一致,否则会报错(2)使用负数可以实现某个维度上元素数量的快速计算,不能用0,且必须被行数/列数整除,否则报错(3)如果直接在数组上调用reshape,则newshape可以不用写成元组#(1)使用reshape时,要注意转换前后数组的元素数量要保持一致,否则会报错#np.reshape(a01,(4,6))#ValueError:cannotreshapearrayofsize30intoshape(4,6)123a01.shape1(30,)1#(2)使用负数可以实现某个维度上元素数量的快速计算,不能用0,且必须被行数/列数整除,否则报错#变成3行n列的数组a01.reshape(3,-1)#会用30除以3,然后得到的数放在-1的位置上123array([[1,2,3,4,5,6,7,8,9,10],[11,12,13,14,15,16,17,18,19,20],[21,22,23,24,25,26,27,28,29,30]])123a01.reshape((-1,1))#将数组变为多行1列的结构,类似表格中的一列(表示一个特征)12array([[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30]])123456789101112131415161718192021222324252627282930a01.reshape((1,-1))#变成一行多列的结构(表示一个记录)1array([[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]])12#(3)如果直接在数组上调用reshape,则newshape可以不用写成元组a01.reshape(6,5)12array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25],[26,27,28,29,30]])123456a01.reshape(3,-1)1array([[1,2,3,4,5,6,7,8,9,10],[11,12,13,14,15,16,17,18,19,20],[21,22,23,24,25,26,27,28,29,30]])123三、Numpy数据类型Python支持的数据类型不足以满足科学计算的需求,因此NumPy添加了很多其他的数据类型,它们占用的内存空间也是不同的。在NumPy中,大部分数据类型名是以数字结尾的,这个数字表示其在内存中占用的位数。名称描述bool_布尔型数据类型(True或者False)int_默认的整数类型(类似于C语言中的long,int32或int64)intc与C的int类型一样,一般是int32或int64intp用于索引的整数类型(类似于C的ssize_t,一般情况下仍然是int32或int64)int8字节(-128to127)int16整数(-32768to32767)int32整数(-2147483648to2147483647)int64整数(-9223372036854775808to9223372036854775807)uint8无符号整数(0to255)uint16无符号整数(0to65535)uint32无符号整数(0to4294967295)uint64无符号整数(0to18446744073709551615)float_float64类型的简写float16半精度浮点数,包括:1个符号位,5个指数位,10个尾数位float32单精度浮点数,包括:1个符号位,8个指数位,23个尾数位float64双精度浮点数,包括:1个符号位,11个指数位,52个尾数位complex_complex128类型的简写,即128位复数complex64复数,表示双32位浮点数(实数部分和虚数部分)complex128复数,表示双64位浮点数(实数部分和虚数部分)非数组对象默认的数据类型是python原生数据类型,数组对象默认的数据类型是Numpy数据类型3.1关于溢出的问题#在创建对象时,尤其是非数组对象,会自动使用原生python的数据类型a=4012type(a)1int1b=np.arange(10)b#创建的对象是数组时,会自动使用numpy的数据类型123array([0,1,2,3,4,5,6,7,8,9])1b.dtype1dtype('int32')1#即使手动指定为python数据类型,也会转换为numpy数据类型c=np.zeros((3,3),dtype=int)c123array([[0,0,0],[0,0,0],[0,0,0]])123c.dtype1dtype('int32')1可以将非数组对象的值转换为numpy数据类型#直接利用数据类型进行转换a12401a1=np.int8(40)a112401type(a1)1numpy.int81#溢出的问题,解决:使用更大的数据类型d=2**20d12310485761d1=np.int8(d)d1#输出0#提醒'''C:\Users\LiLin\AppData\Local\Temp\ipykernel_15164\4039848811.py:1eprecationWarning:NumPywillstopallowingconversionofout-of-boundPythonintegerstointegerarrays.Theconversionof1048576toint8willfailinthefuture.Fortheoldbehavior,usually:np.array(value).astype(dtype)willgivethedesiredresult(thecastoverflows).d1=np.int8(d)'''123456789101112#使用int32进行转换d2=np.int32(d)d2123104857613.2python容器数据结构和numpy数组之间的转换¶3.2.1python容器转numpy数组转换方法:np.array,会将容器中元素的数据类型都转换为numpy的数据类型#列表转数组list1=[1,2,3,4,5,6,7]12type(list1)1list1type(list1[1])1int1arr01=np.array(list1)arr0112array([1,2,3,4,5,6,7])1arr01.dtype1dtype('int32')13.2.2numpy数组转换为python原生数据类型3.2.2.1推导式[int(item)foriteminndadday]arr011array([1,2,3,4,5,6,7])1arr01.dtype1dtype('int32')1list_a01=list(arr01)list_a0112[1,2,3,4,5,6,7]1#使用list转换后,列表中的元素依然是numpy类型type(list_a01[6])12numpy.int321推导式:提取数组中的每个元素,转换为整数,再构成列表list_a01x=[int(each)foreachinarr01]list_a01x12[1,2,3,4,5,6,7]1type(list_a01x)1list1type(list_a01x[5])1int13.2.2.2数组的tolist方法ndarray.tolist():将数组转换为列表,同时将数组中每个元素的数据类型转换为对应的原生python数据类型,没有参数list_a01y=arr01.tolist()list_a01y12[1,2,3,4,5,6,7]1type(list_a01y)1list1type(list_a01y[1])1int1ywillstopallowingconversionofout-of-boundPythonintegerstointegerarrays.Theconversionof1048576toint8willfailinthefuture.Fortheoldbehavior,usually:np.array(value).astype(dtype)willgivethedesiredresult(thecastoverflows).d1=np.int8(d)‘’’```python#使用int32进行转换d2=np.int32(d)d212345678104857613.2python容器数据结构和numpy数组之间的转换¶3.2.1python容器转numpy数组转换方法:np.array,会将容器中元素的数据类型都转换为numpy的数据类型#列表转数组list1=[1,2,3,4,5,6,7]12type(list1)1list1type(list1[1])1int1arr01=np.array(list1)arr0112array([1,2,3,4,5,6,7])1arr01.dtype1dtype('int32')13.2.2numpy数组转换为python原生数据类型3.2.2.1推导式[int(item)foriteminndadday]arr011array([1,2,3,4,5,6,7])1arr01.dtype1dtype('int32')1list_a01=list(arr01)list_a0112[1,2,3,4,5,6,7]1#使用list转换后,列表中的元素依然是numpy类型type(list_a01[6])12numpy.int321推导式:提取数组中的每个元素,转换为整数,再构成列表list_a01x=[int(each)foreachinarr01]list_a01x12[1,2,3,4,5,6,7]1type(list_a01x)1list1type(list_a01x[5])1int13.2.2.2数组的tolist方法ndarray.tolist():将数组转换为列表,同时将数组中每个元素的数据类型转换为对应的原生python数据类型,没有参数list_a01y=arr01.tolist()list_a01y12[1,2,3,4,5,6,7]1type(list_a01y)1list1type(list_a01y[1])1int1
|