当前位置: 首页 > 后端技术 > Python

详解NumPy库,强大的Python科学计算包

时间:2023-03-26 17:21:27 Python

今天来详细解说一个Python库——NumPy。NumPy是Python科学计算的基础包,几乎所有从事Python工作的科学家都利用了NumPy的强大功能。此外,它还被广泛应用于开源项目,如:Pandas、Seaborn、Matplotlib、scikit-learn等。Numpy应用领域是一个栗子,直观感受NumPy的强大。均方误差公式上图是计算均方误差的公式,其中Y_prediction和Y为数组。下面是NumPy代码,一行就可以完成。NumPy计算均方误差NumPy结合可视化库,用几行代码就可以画出下面的数学函数图记得高中学数学的时候,书上得画点我自己,不过现在用的是NumPy,几行代码就搞定了,又快又准。简单了解了NumPy之后,下面就进入详细的讲解1.与list的区别NumPy和list都是数组结构,那么它们有什么区别呢?NumPy数组中所有元素的数据类型都是相同的。NumPy底层充分优化的C语言代码,比list具有更高的计算性能。NumPy提供了一套全面的数学函数,可以直接应用于NumPy数组。2.创建数组NumPy中定义的数组称为ndarray,n-dimensions-array为:n维数组。使用np.array()函数创建NumPy数组>>>importnumpyasnp>>>a=np.array([1,2,3])#createndarrayarray>>>aarray([1,2,3])>>>type(a)a是一个NumPy数组,也是一个numpy.ndarray类对象。这个类定义了几个常用的属性ndarray.ndim:维数,两位数数组ndim是2ndarray.shape:一个元组,每一位代表维度中元素的个数,元组的长度相等tondimndarray.size:数组中元素的总数ndarray.dtype:数组中元素的数据类型ndarray.itemsize:数组中元素的存储大小(以字节为单位)>>>a=np.array([[1,2,3],[4,5,6]])>>>aarray([[1,2,3],[4,5,6]])>>>a.ndim2>>>a.shape(2,3)>>>a.size6>>>a.dtypedtype('int64')>>>a.itemsize8exceptnp.array()除了创建数组,还有以下方式创建数组>>>np.zeros((2,3))#一个二维数组,其中填充0array([[0.,0.,0.],[0.,0.,0.]])>>>np.ones((2,3))#用1填充的二维数组array([[1.,1.,1.],[1.,1.,1.]])>>>np.empty((2,3))#空二维数组,内容为值array([[1.,1.,1.],[1.,1.,1.]])>>>np.arange(6)#用法同范围函数array([0,1,2,3,4,5])>>>np.linspace(0,10,num=5)#以指定的线性区间为初始值,创建数组array([0.,2.5,5.,7.5,10.])>>>rng=np.random.default_rng(0)#创建一个带有随机数的二维数组>>>rng.random((2,3))array([[0.63696169,0.26978671,0.04097352],[0.01652764,0.81327024,0.91275558]])3.访问数组支持index和slice的格式是:arr[i,j,k,...],i,j,k分别代表数组的第0维、第1维、第2维。其中,i,j,k的格式为:s1:s2:s3,分别表示起始下标、结束下标和步长。当步长s3留空时,第二个冒号可以省略,步长为1。以3维数组为例>>>#创建一个5*4的二维数组(5行4列)>>>c=np.array([[0,1,2,3],[10,11,12,13],[20,21,22,23],[30,31,32,33],[40,41,42,43]])>>>carray([[0,1,2,3],[10,11,12,13],[20,21,22,23],[30,31,32,33],[40,41,42,43]])>>>c.shape(5,4)>>>#根据索引,取第1行第2列的元素>>>c[1,2]12>>>#slice,取1~2行,第2列的元素(数组)>>>c[1:3,2]array([12,22])>>>#切片,取1~2行,2~3列的元素(数组)>>>c[1:3,2:4]array([[12,13],[22,23]])>>>#步长=2,得到第1、3行、2~3列元素>>>c[1:6:2,2:4]array([[12,13],[32,33]])如果取最后一个维度和下标为2的元素,可以采取下面的方法>>>c[:,2]array([2,12,22,32,42])如果维度很多,需要写很多:,NumPy提供...可以表示前后任意维度>>>c[...,2]array([2,12,22,32,42])第0维也是如此。4、运算(四种算术运算和函数)NumPy数组支持四种算术运算,将两个数组中相同位置的值进行加、减、乘、除,生成一个新的数组。>>>data=np.array([1,2])>>>ones=np.ones(2,dtype=int)>>>data+onesarray([2,3])NumPy数组加法除了基本的四种算术运算符还支持+=、-=、*=和/=增量赋值运算符,它们可以修改原始数组的值。除了运算符,NumPy还提供了一些用于快速计算数组中值的函数。如sum、min、max和mean等>>>a=np.array([[1,2,3],[4,5,6]])>>>np.sum(a)21中上面的例子,np.sum()函数是用来对二维数组中所有元素求和的。该类函数不仅可以对所有元素进行计算,还支持按指定维度进行计算。如:>>>#根据第0维相加(行相加)>>>a.sum(axis=0)array([5,7,9])>>>#根据第1维相加(列相加)添加)>>>a.sum(axis=1)array([6,15])参数axis指定计算哪个维度。这个参数在NumPy中经常使用。很多教程,包括官网文档,直接告诉读者axis=0表示按行计算,axis=1表示按列计算。我认为这样说是有局限性的。首先,很容易混淆。第二,如果是三维或者更高维,谁是行谁是列。所以,我觉得行和列还是完全不记为好,只记axis的值就是维度。例如,对三维数组的每个维度使用np.sum()>>>a=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])>>>aarray([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])>>>a.shape(2,2,3)根据第0维相加>>>a.sum(axis=0)array([[8,10,12],[14,16,18]])第0维有两个元素,每个元素都是一个二维数组。按照第0维相加就是将这两个二维数组相加,即:[[1,2,3],[4,5,6]]+[7,8,9],[10,11,12]].上面说了NumPy数组相加的时候,可以直接把相同位置的值相加,得到上面的结果。根据第一维添加>>>a.sum(axis=1)array([[5,7,9],[17,19,21]])第一维有4个一维数组,但是由于在第0维的两个元素中,所以分别计算,即:[1,2,3]+[4,5,6]和[7,8,9]+[10,11,12],和最后返回两个一维数组。按照第二个维度相加>>>a.sum(axis=2)array([[6,15],[24,33]])第二个维度是最里面的数,直接把数相加即可。得到4个数字。这样推导每个维度的计算逻辑是最容易理解的,而不是教条式的去死记硬背行或者列。5.广播在上面的运算中,运算符两边的数组是同维的。实际上,可以对不同维度的数组进行加减运算。这时,NumPy会自动调整两边数组的维度相同,然后再进行计算。这个过程称为广播。>>>data=np.array([1.0,2.0])>>>data*1.6array([1.6,3.2])在这里,NumPy将数字1.6广播到一个与data具有相同维度的一维数组中,并且使用1.6Padding,这样就变成了两个一维数组的乘积。当然,也不是所有情况都能广播成功。规则是:从两个数组最右边的维度开始,向左依次判断是否满足以下两个条件:相等,其中一个为1满足一个条件。如果不满足,则会抛出ValueError:operandscouldnotbebroadcasttogether错误。例如:A(4维数组):8x1x6x1B(3维数组):广播后7x1x5(4维数组):从右到左8x7x6x5,或者A维度为1,或者B维度为1,满足规则,可以广播。如果改成A(4维数组):8x1x6x2B(3维数组):7x1x5,就会报错,最右边的两个维度既不相等也不为1。再看一个计算例子:x=np.array([[1],[2],[3],[4]])y=np.array([1,2,3,4])>>>x+yarray([[2,3,4,5],[3,4,5,6],[4,5,6,7],[5,6,7,8]])x将广播A4*4数组[[1,1,1,1],[2,2,2,2],[3,3,3,4],[4,4,4,4]]y也会被广播变成一个4*4的数组[[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]两个或者他们可以直接按照数组规则添加。6.重塑数组NumPy提供了许多函数来改变数组的形状(维度)。重塑函数>>>a=np.arange(10)>>>a.reshape(5,2)array([[0,1],[2,3],[4,5],[6,7],[8,9]])reshape()函数可以修改数组的维数。本例将一维数组修改为5行2列的二维数组。转置函数>>>a=np.array([[1,2],[3,4],[5,6]])>>>a.transpose()array([[1,3,5],[2,4,6]])transpose()函数可以对数组进行转置,达到线性代数中矩阵转置的效果。Arraytranspose这个函数也可以用a.T代替。反转数组np.flip()函数可以反转数组。>>>a=np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])>>>aarray([[1,2,3,4],[5,6,7,8],[9,10,11,12]])>>>np.flip(a)array([[12,11,10,9],[8,7,6,5],[4,3,2,1]])np.flip函数默认将所有元素从左到右,从上到下翻转。当然也可以按照某个维度倒序>>>#按行倒序>>>np.flip(a,axis=0)array([[9,10,11,12],[5,6,7,8],[1,2,3,4]])>>>#按列反转>>>np.flip(a,axis=1)array([[4,3,2,1],[8,7,6,5],[12,11,10,9]])扁平化数组flatten()和ravel()函数可以将多维数组扁平化为一维数组,不同的是前者返回一个新数组,而后者后者只是创建了原始数组的视图。>>>a=np.array([[1,2,3,4],[5,6,7,8]])>>>aarray([[1,2,3,4],[5,6,7,8]])>>>b=a.flatten()>>>barray([1,2,3,4,5,6,7,8])>>>b[0]=10>>>数组([10,2,3,4,5,6,7,8])>>>数组([[1,2,3,4],[5,6,7,8]])a为二维数组,经flatten函数展平后变为一维数组b。修改b数组的值不会影响数组a。>>>a=np.array([[1,2,3,4],[5,6,7,8]])>>>b=a.ravel()>>>barray([1,2,3,4,5,6,7,8])>>>b[0]=10>>>aarray([[10,2,3,4],[5,6,7,8]])数组a通过ravel函数展平为一维数组b,修改b中的值会影响数组a。这里会发现一个现象,数组a还是一个二维数组,也就是说raval只是创建a的视图,并没有改变a本身的存储结构。如果想修改b而不影响a,可以调用copy()函数>>>c=b.copy()>>>carray([10,2,3,4,5,6,7,8])>>>c[0]=100>>>aarray([[10,2,3,4],[5,6,7,8]])copy()函数将创建一个新数组并填充它与原数组的值,所以修改新数组不会影响原数组。这个过程也称为深拷贝。重塑数组的函数有很多,比如:np.sort():排序np.hstack():横向合并数组np.vstack():纵向合并数组np.concatenate():按维度合并数组等等等等.用法并不复杂,可以参考官方文档学习。7.AdvancedAccess7.1IndexingArraysSection3解释了在访问数组时,它们都是通过数字访问的。NumPy支持访问数组格式的数组。>>>a=np.arange(12)>>>i=np.array([1,1,3,8,5])>>>a[i]数组([1,1,3,8,5])数组i是一个索引数组,里面的值可以作为a的下标来访问。多维数组也可以用同样的方式访问。>>>a=np.array([[0,0,0],[255,0,0],[0,255,0],[0,0,255],[255,255,255]])>>>aarray([[0,0,0],[255,0,0],[0,255,0],[0,0,255],[255,255,255]])>>>i=np.array([[0,1,2,0],[0,3,4,0]])>>>a[i]array([[[0,0,0],[255,0,0],[0,255,0],[0,0,0]],[[0,0,0],[0,0,255],0,5[255,5],0,0]]])访问多维数组,索引数组i中的值将作为数组a中第0维的下标。当然,索引数组不仅仅可以访问第0维,还支持多个索引数组访问同一个数组的多个维度。>>>a=np.arange(12).reshape(3,4)>>>aarray([[0,1,2,3],[4,5,6,7],[8,9,10,11]])>>>i=np.array([[0,1],[1,2]])>>>j=np.array([[2,1],[3,3]])>>>a[i,j]array([[2,5],[7,11]])索引数组的维度必须相同,第一个索引数组i访问第0维,第二个两位索引数组j访问第一个维度,依此类推。i和j相同位置的数字正好对应数组a中某行某列的元素。7.2布尔数组索引数组可以是布尔类型的数组,True表示保留元素,False表示删除元素。>>>a=np.arange(12).reshape(3,4)>>>b=a>4>>>a[b]array([5,6,7,8,9,10,11])>>>a[a>4]array([5,6,7,8,9,10,11])因为a和b的形状相同,所以返回的结果是一个一维数组。当然也可以指定维度来过滤>>>a=np.arange(12).reshape(3,4)>>>b1=np.array([False,True,True])>>>b2=np.array([True,False,True,False])>>>a[b1,:]array([[4,5,6,7],[8,9,10,11]])>>>a[:,b2]array([[0,2],[4,6],[8,10]])>>>a[b1,b2]array([4,10])在这里,我们把NumPy的结构、访问和操作都有解释,涵盖了NumPy的大部分常用功能。有了这么详细的解释,相信大家直接使用或者阅读官方文档都会很轻松。以上就是本次分享的全部内容。觉得文章还不错的话,请关注公众号:Python编程学习圈,每日干货分享,发送“J”还能领取大量学习资料。或者去编程学习网了解更多编程技术知识。