购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.1 NumPy库

NumPy(Numerical Python)是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外,也针对数组运算提供大量的数学函数库。NumPy对于scikit-learn来说是至关重要的,因为scikit-learn使用NumPy数组形式的数据来进行处理,所以需要把数据都转换成NumPy数组的形式,而多维数组也是NumPy的核心功能之一。

NumPy是一个运行速度非常快的数学库,主要用于数组计算,包含:

(1)一个强大的N维数组对象ndarray。

(2)广播功能函数。

(3)整合C/C++/FORTRAN代码的工具。

(4)线性代数、傅里叶变换、随机数生成等功能。

2.1.1 NumPy创建数组

NumPy数组是一个多维数组,称为ndarray。NumPy的创建方法有以下三种,分别为:用特殊函数创建、从已有的数组创建数组以及从数值范围创建数组。

1.特殊函数创建数组

注意: 在ndarray结构中,里面的元素必须是同一类型的,如果不是,会自动地向下进行。

【例2-1】 创建数组和数列。

     import numpy as np
     #numpy和列表的形式区别(有无逗号)
     ar=np.array([1,2,3,4,5])
     list1=[1,2,3,4,5]
     print(ar,type(ar))        #输出结果中没有逗号分隔
     print(list1,type(list1))          #输出结果中有逗号分隔

运行程序,输出如下。

     [1 2 3 4 5]<class  'numpy.ndarray'>
     [1, 2, 3, 4, 5]<class 'list'>

ndarray数组除了可以使用底层ndarray构造器来创建外,也可以通过以下几种方式来创建。

1)numpy.zeros()方法

numpy.zeros()方法用于创建指定大小的数组,数组元素以0来填充,方法的格式为:

     numpy.zeros(shape,dtype=float,order= 'C')

其中,shape为数组形状;dtype为数据类型,可选;order取'C'时用于C的行数组,取'F'时用于FORTRAN的列数组。

【例2-2】 利用numpy.zeros()方法创建指定大小的0数组。

     import numpy as np
     #默认为浮点数
     x=np.zeros(6)
     print(x)
     #设置类型为整数
     y=np.zeros((6,),dtype=int)
     print(y)
     #自定义类型
     z=np.zeros((2,2),dtype=[('x','i4'),('y','i4')])
     print(z)

运行程序,输出如下。

     [0.0.0.0.0.0.]
     [0 0 0 0 0 0]
     [[(0,0)(0,0)]
      [(0,0)(0,0)]]

2)numpy.empty()方法

numpy.empty()方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。方法的格式为:

     numpy.empty(shape,dtype=float,order= 'C')

其中,shape为数组形状;dtype为数据类型,可选;order有'C'和'F'两个选项,分别代表行优先和列优先。

【例2-3】 利用numpy.empty()方法创建一个空数组。

     import numpy as np
     x=np.empty([3,2],dtype= int)
     print(x)

运行程序,输出如下。

     [[857761391 543236140]
      [1701868915 1952804466]
      [1953068832 174137448]]

3)numpy.ones()方法

numpy.ones()方法用于创建指定形状的数组,数组元素以1来填充,方法的格式为:

     numpy.ones(shape,dtype=None,order= 'C')

其中,shape为数组形状;dtype为数据类型,可选;order取'C'时用于C的行数组,取'F'时用于FORTRAN的列数组。

【例2-4】 利用numpy.ones()方法创建一个全1数组。

     import numpy as np
     #默认为浮点数
     x=np.ones(5)
     print(x)
     #自定义类型
     x=np.ones([2,2],dtype= int)
     print(x)

运行程序,输出如下。

     [1.1.1.1.1.]
     [[1 1]
      [1 1]]

4)numpy.full()方法

numpy.full()方法用于创建指定形状的数组,数组元素以fill_value来填充,方法的格式为:

     numpy.full(shape,fill_value,dtype=None,order='C')

其中,shape为新数组的形状大小;fill_value将被赋值给新数组的元素值;dtype为指定数组元素的数据类型;order有'C'和'F'两个选项,分别代表行优先和列优先。

【例2-5】 创建一个填充给定值的数组。

     import numpy as np
     np.full([2,3],3,dtype=int)

运行程序,输出如下。

     array([[3,3,3],
             [3,3,3]])
2. 从已有的数组创建数组

除了可以利用函数创建特殊数组外,NumPy还提供了相关函数用于实现从已有的数组创建数组,下面对各函数进行介绍。

1)numpy.asarray()函数

numpy.asarray()类似numpy.array(),但numpy.asarray()的参数只有三个,比numpy.array()少两个。numpy.asarray()函数的格式为:

     numpy.asarray(a,dtype=None,order=None)

其中,a为任意形式的输入参数,可以是列表、列表的元组、元组、元组的元组、元组的列表、多维数组;dtype为数据类型,可选;order可选,有'C'和'F'两个选项,分别代表行优先和列优先。

【例2-6】 利用numpy.asarray()函数实现从已有数组创建数组。

     #将列表转换为ndarray
     import numpy as np
     x=[1,2,3]
     a=np.asarray(x)
     print('将列表转换为ndarray:',a)
     #将元组转换为ndarray
     x=(1,2,3)
     a=np.asarray(x)
     print('将元组转换为ndarray:',a)
     #将元组列表转换为ndarray
     x=[(1,2,3),(4,5)]
     a=np.asarray(x)
     print('将元组列表转换为ndarray:',a)
     #设置了dtype参数
     x=[1,2,3]
     a=np.asarray(x,dtype=float)
     print('设置了dtype参数:',a)

运行程序,输出如下。

     将列表转换为ndarray:[1 2 3]
     将元组转换为ndarray:[1 2 3]
     将元组列表转换为ndarray:[(1,2,3)(4,5)]
     设置了dtype参数:[1.2.3.]

2)numpy.frombuffer()函数

numpy.frombuffer()接受buffer输入参数,以流的形式读入转换的ndarray对象。函数的格式为:

     numpy.frombuffer(buffer,dtype=float,count=-1,offset=0)

其中,buffer可以是任意对象,以流的形式读入;dtype为返回数组的数据类型,可选;count为读取的数据数量,默认为-1,读取所有数据;offset为读取的起始位置,默认为0。

【例2-7】 利用numpy.frombuffer()函数接受buffer输入转换数组。

     import numpy as np
     #buffer是字符串的时候,Python 3默认str是Unicode类型,所以要转成bytestring需要在原str
     #前加上b
     s=b'HelloWorld'
     a=np.frombuffer(s,dtype='S1')
     print(a)

运行程序,输出如下。

     [b'H'b'e'b'l'b'l'b'o'b''b'W'b'o'b'r'b'l'b'd']

3)numpy.fromiter()函数

numpy.fromiter()从可迭代对象中建立ndarray对象,返回一维数组。函数的格式为:

     numpy.fromiter(iterable,dtype,count=-1)

其中,iterable为可迭代对象;dtype为返回数组的数据类型;count为读取的数据数量,默认为-1,读取所有数据。

【例2-8】 利用numpy.fromiter()函数从对象中建立数组。

     import numpy as np
     #使用range函数创建列表对象
     list=range(5)
     it=iter(list)
     #使用迭代器创建ndarray
     x=np.fromiter(it,dtype=float)
     print(x)

运行程序,输出如下。

     [0.1.2.3.4.]
3.从数值范围创建数组

NumPy从数值范围创建数组主要有:创建指定范围的数组(numpy.arange())、创建指定范围的等差数列(numpy.linspace())、创建指定范围的等比数列(numpy.logspace())。

1)创建指定范围的数组

numpy包中使用arange()函数创建数值范围并返回ndarray对象,函数格式为:

     numpy.arange(start,stop,step,dtype)

其中,start为起始值,默认为0;stop为结束值,必需,传一个值的时候虽然是赋值给了start,但却是一个结束值;step为步长,默认为1;dtype为数据类型,如果没有提供,则会使用输入数据的类型。

【例2-9】 利用numpy.arange()函数创建指定的数组。

     import numpy as np
     a=np.arange(5)
     b=np.arange(5,dtype=float)
     c=np.arange(10,20,2)
     print('a:',a,'\n'
              'b:',b,'\n'
              'c:',c,'\n')

运行程序,输出如下。

     a:[0 1 2 3 4]
     b:[0.1.2.3.4.]
     c:[10 12 14 16 18]

2)创建指定范围的等差数列

numpy.linspace()函数用于创建一个一维数组,数组是由一个等差数列构成的,函数格式为:

     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的数据类型。

【例2-10】 利用numpy.linspace()创建指定范围的等差数列。

     #用到三个参数,设置起始点为1,终止点为10,数列个数为10
     import numpy as np
     a=np.linspace(1,10,10)
     print('指定范围为10的10个数列:',a)
     #设置元素全部是1的等差数列
     a=np.linspace(1,1,10)
     print('元素全部是1的等差数列:',a)
     #endpoint设为False,不包含终止值
     a=np.linspace(10,20,5,endpoint=False)
     print('endpoint设为False,不包含终止值:',a)
     #将endpoint设为True,则会包含20
     a=np.linspace(1,10,10,retstep=True)
     print('endpoint设为True的数列:',a)
     #拓展例子
     b=np.linspace(1,10,10).reshape([10,1])
     print('拓展例子:',b)

运行程序,输出如下。

     指定范围为10的10个数列:[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
     元素全部是1的等差数列:[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     endpoint设为False,不包含终止值:[10. 12. 14. 16. 18.]
     endpoint设为True的数列:(array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]),1.0)
     拓展例子:[[ 1.]
     [ 2.]
     [ 3.]
     [ 4.]
     [ 5.]
     [ 6.]
     [ 7.]
     [ 8.]
     [ 9.]
     [ 10.]]

3)创建指定范围的等比数列

numpy.logspace()函数用于创建一个等比数列。函数格式为:

     numpy.logspace(start,stop,num=50,endpoint=True,base=10.0,dtype=None)

其中,start为序列的起始值,为base**start;stop为序列的终止值,为base**stop;如果endpoint为True,该值包含于数列中;num为要生成的等步长的样本数量,默认为50;endpoint值为Ture时,数列中包含stop值,反之不包含,默认是True;base为对数log的底数;dtype为ndarray的数据类型。

值得注意的是,start和stop是数列的下标值,它们的底数是base。

【例2-11】 利用numpy.logspace()函数创建指定范围的等比数列。

     import numpy as np
     #默认底数是10
     a=np.logspace(1.0,2.0,num=10)
     print('默认底数是10的数列:',a)
     #将对数的底数设置为2
     a=np.logspace(0,9,10,base=2)
     print('对数的底数设置为2的数列:',a)

运行程序,输出如下。

     默认底数是10的数列:[10. 12.91549665 16.68100537 21.5443469 27.82559402
        35.93813664 46.41588834 59.94842503 77.42636827 100.   ]
     对数的底数设置为2的数列:[1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]

2.1.2 数组操作

NumPy中包含一些函数用于处理数组,大概可分为以下几类:修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除等。

1.修改数组形状

在NumPy中提供了相关函数实现数组形状的修改,如表2-1所示。

表2-1 修改数组形状

1)numpy.reshape()函数

numpy.reshape()函数可以在不改变数据的条件下修改形状,函数的格式为:

     numpy.reshape(arr,newshape,order='C')

其中,arr为要修改形状的数组;newshape为整数或者整数数组,新的形状应当兼容原有形状;order取'C'时按行,取'F'时按列,取'A'时按原顺序,取'K'时按元素在内存中的出现顺序。

【例2-12】 利用reshape()函数改变给定数组的形状。

     import numpy as np
     a=np.arange(8)
     print('原始数组:',a)
     b=a.reshape(4,2)
     print('修改后的数组:',b)

运行程序,输出如下。

     原始数组:[0 1 2 3 4 5 6 7]
     修改后的数组:[[0 1]
                   [2 3]
                   [4 5]
                   [6 7]]

2)numpy.ndarray.flat()函数

numpy.ndarray.flat()是一个数组元素迭代器,下面直接通过实例来演示它的用法。

【例2-13】 利用numpy.ndarray.flat()更改数组的形状。

     import numpy as np
     a=np.arange(8).reshape(4,2)
     print('原始数组:')
     for row in a:
          print(row)
     #对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器
     print('迭代后的数组:')
     for element in a.flat:
          print(element)

运行程序,输出如下。

     原始数组:
     [0 1]
     [2 3]
     [4 5]
     [6 7]
     迭代后的数组:
     0
     1
     2
     3
     4
     5
     6
     7

3)numpy.ndarray.flatten()

numpy.ndarray.flatten()返回一份数组副本,对副本所做的修改不会影响原始数组,函数的格式为:

     ndarray.flatten(order='C')

其中,order取'C'时按行,取'F'时按列,取'A'时按原顺序,取'K'时按元素在内存中的出现顺序。

【例2-14】 利用numpy.ndarray.flatten()改变数组的形状。

     import numpy as np
     a=np.arange(8).reshape(2,4)
     print('原数组:',a)
     #默认按行
     print('展开的数组:',a.flatten())
     print('以F风格顺序展开的数组:',a.flatten(order= 'F'))

运行程序,输出如下。

     原数组:[[0 1 2 3]
     [4 5 6 7]]
     展开的数组:[0 1 2 3 4 5 6 7]
     以F风格顺序展开的数组:[0 4 1 5 2 6 3 7]

4)numpy.ravel()

numpy.ravel()展平的数组元素,顺序通常是“C风格”,返回的是数组视图,修改会影响原始数组。函数的格式为:

     numpy.ravel(a,order='C')

其中,a为原始数据;order取'C'时按行,取'F'时按列,取'A'时按原顺序,取'K'时按元素在内存中的出现顺序。

【例2-15】 利用numpy.ravel()对所创建的数据进行展平。

     import numpy as np
     a=np.arange(8).reshape(2,4)
     print('原数组:',a)
     print('调用ravel函数之后:',a.ravel())
     print('以F风格顺序调用ravel函数之后:',a.ravel(order= 'F'))

运行程序,输出如下。

     原数组:[[0 1 2 3]
     [4 5 6 7]]
     调用ravel函数之后:[0 1 2 3 4 5 6 7]
     以F风格顺序调用ravel函数之后:[0 4 1 5 2 6 3 7]
2.翻转数组

数组的翻转也是数组比较重要的操作之一,属于形状变化或维度变化的操作。可以通过以下方法实现,这些方法有属于ndarray的方法,也有属于NumPy的方法。除此以外,属性转置(ndarray.T())也可以实现数组行列翻转的功能,如表2-2所示。

表2-2 翻转数组函数

1)ndarray.transpose()函数

ndarray.transpose()函数用于返回转置轴的数组视图。函数的格式为:

     ndarray.transpose(* axis)

其中,axis可选None,整数元组或者 n 个整数;返回值为数组的视图。

(1)axis=None或无参数时,反转轴的顺序。

(2)axis=整数数组,元组中第 j 个位置的 i 表示 a 的第 i 个轴变为 a .transpose()的第 j 个轴。

(3)axis= n 个整数,这种形式与元组形式功能相同。

【例2-16】 利用ndarray.transpose()函数返回数组视图。

     import numpy as np
     a=np.arange(12).reshape(3,4)
     print('原数组:',a)
     print('对换数组:',np.transpose(a))

运行程序,输出如下。

     原数组:[[0 1 2 3]
     [4 5 6 7]
     [8 9 10 11]]
     对换数组:[[0 4 8]
     [1 5 9]
     [2 6 10]
     [3 7 11]]

2)ndarray.T()函数

数组中的属性(ndarray.T)是转置的意思,可以将数组进行行列交换。

【例2-17】 利用ndarray.T()对数组进行转置。

     import numpy as np
     a=np.arange(12).reshape(3,4)
     print('原数组:',a)
     print('转置数组:',a.T)

运行程序,输出如下。

     原数组:[[0 1 2 3]
     [4 5 6 7]
     [8 9 10 11]]
     转置数组:[[0 4 8]
     [1 5 9]
     [2 6 10]
     [3 7 11]]

3)ndarray.moveaxis()函数

ndarray.moveaxis()实现将数组的轴移动到新位置。函数的格式为:

     numpy.moveaxis(a,source,destination)

其中,a为接收ndarray,需要转动轴的数组;source为接收整数或者整数序列,要移动的轴的原始位置,必须是唯一的;destination为接收整数或者整数序列,每个原始轴的目标位置,也必须是唯一的。

【例2-18】 利用ndarray.moveaxis()函数将数组的轴移动到新位置。

     import numpy as np
     #创建了三维的ndarray
     a=np.arange(8).reshape(2,2,2)
     print('原数组:',a)
     print('获取数组中一个值:',np.where(a==6))
     print(a[1,1,0])
     #将轴2滚动到轴0(宽度到深度)
     print('调用rollaxis()函数:')
     b=np.rollaxis(a,2,0)
     print(b)
     #查看元素a[1,1,0],即6的坐标,变成[0,1,1]
     #最后一个0移动到最前面
     print(np.where(b==6))
     #将轴2滚动到轴1(宽度到高度)
     print('调用rollaxis()函数:')
     c=np.rollaxis(a,2,1)
     print(c)
     #查看元素a[1,1,0],即6的坐标,变成[1,0,1]
     #最后的0和它前面的1对换位置
     print(np.where(c==6))

运行程序,输出如下。

     原数组:[[[0 1]
       [2 3]]
     
     [[4 5]
       [6 7]]]
     获取数组中一个值:(array([1],dtype=int64),array([1],dtype=int64),array([0],dtype=
     int64))
     6
     调用rollaxis()函数:
     [[[0 2]
       [4 6]]
     
     [[1 3]
       [5 7]]]
     (array([0],dtype=int64),array([1],dtype=int64),array([1],dtype=int64))
     调用rollaxis()函数:
     [[[0 2]
       [1 3]]
     
     [[4 6]
       [5 7]]]
     (array([1],dtype=int64),array([0],dtype=int64),array([1],dtype=int64))

4)numpy.swapaxis()函数

numpy.swapaxis()函数用于交换数组的两个轴,函数格式为:

     numpy.swapaxis(arr,axis1,axis2)

其中,arr为输入的数组;axis1为对应第一个轴的整数;axis2为对应第二个轴的整数。

【例2-19】 利用numpy.swapaxis()函数交换数组的两个轴。

     import numpy as np
     #创建了三维的ndarray
     a=np.arange(8).reshape(2,2,2)
     print('原数组:',a)
     #现在交换轴0(深度方向)到轴2(宽度方向)
     print('调用 swapaxis()函数后的数组:')
     print(np.swapaxis(a,2,0))

运行程序,输出如下。

     原数组:[[[0 1]
       [2 3]]
     
     [[4 5]
       [6 7]]]
     调用swapaxis()函数后的数组:
     [[[0 4]
       [2 6]]
     [[1 5]
       [3 7]]]

5)numpy.rollaxis()函数

numpy.rollaxis()函数向后滚动特定的轴到一个特定位置,函数格式为:

     numpy.rollaxis(arr,axis,start)

其中,arr为数组;axis为要向后滚动的轴,其他轴的相对位置不会改变;start默认为零,表示完整的滚动。

【例2-20】 利用numpy.rollaxis()函数向后滚动特定的轴到特定位置。

     import numpy as np
     #创建了三维的ndarray
     a=np.arange(8).reshape(2,2,2)
     print('原数组:',a)
     print('获取数组中一个值:')
     print(np.where(a==6))
     print(a[1,1,0])
     #将轴2滚动到轴0(宽度到深度)
     print('调用rollaxis()函数:')
     b=np.rollaxis(a,2,0)
     print(b)
     #查看元素a[1,1,0],即6的坐标,变成[0,1,1]
     #最后一个0移动到最前面
     print(np.where(b==6))
     #将轴2滚动到轴1(宽度到高度)
     print('调用rollaxis()函数:')
     c=np.rollaxis(a,2,1)
     print(c)
     #查看元素a[1,1,0],即6的坐标,变成[1,0,1]
     #最后的0和它前面的1对换位置
     print(np.where(c==6))

运行程序,输出如下。

     原数组:[[[0 1]
       [2 3]]
     
     [[4 5]
      [6 7]]]
     获取数组中一个值:
     (array([1],dtype=int64),array([1],dtype=int64),array([0],dtype=int64))
     6
     调用rollaxis()函数:
     [[[0 2]
       [4 6]]
     
     [[1 3]
       [5 7]]]
     (array([0],dtype=int64),array([1],dtype=int64),array([1],dtype=int64))
     调用rollaxis()函数:
     [[[0 2]
       [1 3]]
     
     [[4 6]
       [5 7]]]
     (array([1],dtype=int64),array([0],dtype=int64),array([1],dtype=int64))
3.修改数组维度

在NumPy中,除了可以改变数组的形状外,还可以修改数组的维度,表2-3列出了相关函数。

表2-3 修改数组维度函数

1)numpy.broadcast()函数

numpy.broadcast()函数用于模仿广播机制。它返回一个对象,该对象封装了将一个数组广播到另一个数组的结果。该函数将两个数组作为输入参数。

【例2-21】 演示numpy.broadcast()函数的使用。

     import numpy as np
     x=np.array([[-1],[3],[2]])
     y=np.array([4,5,6])
     #对y广播x
     b=np.broadcast(x,y)
     #拥有iterator属性,基于自身组件的迭代器元组
     print('对y广播x:')
     r,c=b.iters
     #Python 3.x为next(context),Python 2.x为context.next()
     print(next(r),next(c))
     print(next(r),next(c))
     #shape属性返回广播对象的形状
     print('广播对象的形状:')
     print(b.shape)
     #手动使用broadcast将x与y相加
     b=np.broadcast(x,y)
     c=np.empty(b.shape)
     print('手动使用broadcast将x与y相加:')
     print(c.shape)
     c.flat=[u+v for(u,v)in b]
     print('调用flat()函数:')
     print(c)
     #获得了和NumPy内建的广播支持相同的结果
     print('x与y的和:')
     print(x+y)

运行程序,输出如下。

     对y广播x:
     -1 4
     -1 5
     广播对象的形状:
     (3,3)
     手动使用broadcast将x与y相加:
     (3,3)
     调用flat()函数:
     [[3.4.5.]
      [7.8.9.]
      [6.7.8.]]
     x与y的和:
     [[3 4 5]
      [7 8 9]
      [6 7 8]]

2)numpy.broadcast_to()函数

numpy.broadcast_to()函数将数组广播到新形状。它在原始数组上返回只读视图,通常不连续。如果新形状不符合NumPy的广播规则,该函数可能会抛出ValueError。

【例2-22】 演示numpy.broadcast_to()函数的用法。

     import numpy as np
     #将一行三列的数组广播到四行三列
     a=np.arange(3).reshape(1,3)
     print(a)
     print(np.broadcast_to(a,(4,3)))
     [[0 1 2]]
     [[0 1 2]
      [0 1 2]
      [0 1 2]
      [0 1 2]]
     [[0]
      [1]
      [2]]
     #将三行一列的数组广播到四行三列,报错
     a=np.arange(3).reshape(3,1)
     print(a)
     print(np.broadcast_to(a,(4,3)))
     ValueError:operands    could  not  be broadcast  together  with  remapped  shapes[original-  >
     remapped]:(3,1)and requested shape(4,3)

3)numpy.expand_dims()函数

numpy.expand_dims()函数通过在指定位置插入新的轴来扩展数组形状,函数格式为:

     numpy.expand_dims(arr,axis)

其中,arr为输入数组;axis为新轴插入的位置。

【例2-23】 利用numpy.expand_dims()函数扩展数组形状。

     import numpy as np
     x=np.array(([1,2],[3,4]))
     print('数组x:')
     print(x)
     y=np.expand_dims(x,axis=0)
     print('数组y:')
     print(y)
     print('数组x和y的形状:')
     print(x.shape,y.shape)
     #在位置1插入轴
     y=np.expand_dims(x,axis=1)
     print('在位置1插入轴之后的数组y:')
     print(y)
     print('x.ndim和y.ndim:')
     print(x.ndim,y.ndim)
     print('x.shape和y.shape:')
     print(x.shape,y.shape)

运行程序,输出如下。

     数组x:
     [[1 2]
      [3 4]]
     数组y:
     [[[1 2]
       [3 4]]]
     数组x和y的形状:
     (2,2)(1,2,2)
     在位置1插入轴之后的数组y:
     [[[1 2]]
     
      [[3 4]]]
     x.ndim和y.ndim:
     2 3
     x.shape和y.shape:
     (2,2)(2,1,2)

4)numpy.squeeze()函数

numpy.squeeze()函数从给定数组的形状中删除一维的条目,函数格式为:

     numpy.squeeze(arr,axis)

其中,arr为输入数组;axis为整数或整数元组,用于选择形状中一维条目的子集。

【例2-24】 利用numpy.squeeze()函数在给定数组中删除一维的条目。

     import numpy as np
     x=np.arange(8).reshape(1,2,4)
     print('数组x:')
     print(x)
     y=np.squeeze(x)
     print('数组y:')
     print(y)
     print('数组x和y的形状:')
     print(x.shape,y.shape)

运行程序,输出如下。

     数组x:
     [[[0 1 2 3]
       [4 5 6 7]]]
     数组y:
     [[0 1 2 3]
      [4 5 6 7]]
     数组x和y的形状:
     (1,2,4)(2,4)
4.连接数组

连接意味着将两个或多个数组的内容放在单个数组中。在SQL中,基于键来连接表,而在NumPy中,按轴连接数组。NumPy提供了相关函数实现数组连接,如表2-4所示。

表2-4 连接数组

【例2-25】 综合演示数组的各种连接效果。

     import numpy as np
     arr1=np.array([[[-1,2],[-3,4]],[[-5,6],[-7,8]]])
     arr2=np.array([[[9,10],[11,12]],[[13,14],[15,16]]])
     """级联拼接"""
     arr=np.concatenate((arr1,arr2))#默认在第0维上进行数组的连接
     arr_1=np.concatenate((arr1,arr2),axis=1)#axis指定拼接的维度,axis=1表示在第1维上对
     #数组进行拼接
     arr_2=np.concatenate((arr1,arr2),axis=2)#axis指定拼接的维度,axis=2表示在第2维上对
     #数组进行拼接
     
     """堆栈拼接"""
     arr_3=np.stack((arr1,arr2))      #默认在第0维上进行数组的连接
     arr_4=np.stack((arr1,arr2),axis=1)         #在第1维上进行数组的连接
     arr_5=np.stack((arr1,arr2),axis=2)         #在第2维上进行数组的连接
     arr_6=np.stack((arr1,arr2),axis=3)         #在第3维上进行数组的连接
     
     """其他方法"""
     arr_7=np.hstack((arr1,arr2))                #按行堆叠,相当于级联axis=1的方法
     arr_8=np.vstack((arr1,arr2))                #按列堆叠,相当于级联axis=0的方法
     arr_9=np.dstack((arr1,arr2))                #按深度堆叠,相当于级联axis=2的方法
     
     print("原始数组:")
     print(arr1)
     print("数组类型:",arr1.shape)
     print()
     print(arr2)
     print("数组类型:",arr2.shape)
     print()
     
     print("使用concatenate()函数连接")
     print()
     print("默认在第0维上进行数组的连接")
     print(arr)
     print("数组类型:",arr.shape)
     print()
     
     print()
     print("在第1维上进行数组的连接")
     print(arr_1)
     print("数组类型:",arr_1.shape)
     print()
     
     print("在第2维上进行数组的连接")
     print(arr_2)
     print("数组类型:",arr_2.shape)
     print()
     
     print("使用stack()函数连接")
     print()
     
     print("默认在第0维上进行数组的连接")
     print(arr_3)
     print("数组类型:",arr_3.shape)
     print()
     
     print("在第1维上进行数组的连接")
     print(arr_4)
     print("数组类型:",arr_4.shape)
     print()
     
     print("在第2维上进行数组的连接")
     print(arr_5)
     print("数组类型:",arr_5.shape)
     print()
     
     print("在第3维上进行数组的连接")
     print(arr_6)
     print("数组类型:",arr_6.shape)
     print()
     
     print("按行堆叠")
     print(arr_7)
     print("数组类型:",arr_7.shape)
     print()
     
     print("按列堆叠")
     print(arr_8)
     print("数组类型:",arr_8.shape)
     print()
     
     print("按高(深)堆叠")
     print(arr_9)
     print("数组类型:",arr_9.shape)
     print()

运行程序,输出如下。

5.分割数组

在NumPy中,数组可以进行水平、垂直或深度分割,相关的函数如表2-5所示。可以将数组分割成相同大小的子数组,也可以指定原数组中需要分割的位置。

表2-5 数组分割函数

1)numpy.split()函数

numpy.split()函数沿特定的轴将数组分割为子数组,函数格式为:

     numpy.split(ary,indices_or_sections,axis)

其中,ary为被分割的数组;indices_or_sections如果是一个整数,就用该数平均切分,如果是一个数组,则沿轴的位置切分;axis为沿着哪个维度进行切分,默认为0,纵向切分(垂直方向),为1时,横向切分(水平方向)。

axis的值看作是x轴的值,为0时在y轴上即垂直方向,为1时在x轴上即水平方向。axis=0纵向切分,即对着y轴切开;axis=1横向切分,即对着x轴切开。

注意: indices_or_sections为整数平均切分时,原数组一定要能平均切分,如果不能则抛出异常。

【例2-26】 利用numpy.split()函数实现数组的分割。

     x=np.arange(1,9)
     print(x)
     [1 2 3 4 5 6 7 8]
     a=np.split(x,4)#传递整数4表示平均切分为4等份
     print(a)
     [array([1,2]),array([3,4]),array([5,6]),array([7,8])]
     print(a[0])
     [1 2]
     print(a[1])
     [3 4]
     print(a[2])
     [5 6]
     print(a[3])
     [7 8]
     
     #传递数组进行分割
     #[3,5]表示将原数组按索引0~2为一组,3~4为一组,5~末尾为一组切分
     b=np.split(x,[3,5])
     print(b)
     [array([1,2,3]),array([4,5]),array([6,7,8])]
     
     #split分割二维数组
     a=np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])#创建二维数组
     print(a)
     [[1 2 3]
      [4 5 6]
      [7 8 9]
      [10 11 12]]
     
     r=np.split(a,2,axis=0)#整数2表示平均切分为2等份,axis=0表示纵向切分
     print(r)
     [array([[1,2,3],
             [4,5,6]]),array([[7,8,9],
             [10,11,12]])]
     print(r[0])
     [[1 2 3]
      [4 5 6]]
     print(r[1])
     [[7 8 9]
      [10 11 12]]
     
     x,y=np.split(a,2,axis=0)
     print(x)
     [[1 2 3]
      [4 5 6]]
     print(y)
     [[7 8 9]
      [10 11 12]]

2)numpy.hsplit()函数

numpy.hsplit()函数可以水平分割数组,该函数有两个参数,第1个参数表示待分割的数组,第2个参数表示要将数组水平分割成几个小数组。

注意: 第2个参数值必须可以整除待分割数组的列数,即原数组必须可以平均等分,如果不能则抛出异常。

【例2-27】 利用numpy.hsplit()函数对数组进行水平分割。

     import numpy as np
     harr=np.floor(10 * np.random.random((2,6)))
     print('原数组:')
     print(harr)
     print('拆分后数组:')
     print(np.hsplit(harr,3))

运行程序,输出如下。

     原数组:
     [[5. 1. 2. 7. 6. 7.]
      [4. 3. 8. 3. 7. 7.]]
     拆分后数组:
     [array([[5., 1.],
             [4., 3.]]),array([[2., 7.],
             [8., 3.]]),array([[6., 7.],
             [7., 7.]])]

3)numpy.vsplit()函数

numpy.vsplit()函数可以垂直分割数组,该函数有两个参数,第1个参数表示待分割的数组,第2个参数表示将数组垂直分割成几个小数组。

【例2-28】 利用numpy.vsplit()函数分割数组。

     import numpy as np
     a=np.arange(16).reshape(4,4)
     print('第一个数组:')
     print(a)
     print('竖直分割:')
     b=np.vsplit(a,2)
     print(b)

运行程序,输出如下。

     第一个数组:
     [[0 1 2 3]
      [4 5 6 7]
      [8 9 10 11]
      [12 13 14 15]]
     竖直分割:
     [array([[0,1,2,3],
             [4,5,6,7]]),array([[8, 9,10,11],
             [12,13,14,15]])]

4)array_split()函数

对于一个长度为 L 的数组,该函数是这么拆的:前 L % n 个组的大小是 L // n +1,剩下组的大小是 L // n 。其中,“//”表示下取整(即np.floor()), n 代表划分后数组的个数。

【例2-29】 利用array_split()函数分割数组。

     #生成要组合的两个数组
     array1=np.arange(14).reshape(2,7)
     ar=np.array_split(array1,2,axis=1)#按列分割成两份.此处若用np.split()则会报错.
     print(ar)

运行程序,输出如下。

     [array([[0, 1, 2, 3],
             [7, 8, 9,10]]),array([[4, 5, 6],
             [11,12,13]])]
6.数组元素的添加与删除

在NumPy中对数组元素进行添加和删除操作,可以使用append()函数和insert()函数为数组添加元素,或者使用delete()函数返回删除了某个轴的子数组的新数组,以及使用unique()函数寻找数组内的唯一元素。

1)numpy.append()函数

numpy.append()函数是在数组的末尾添加元素,该函数会返回一个新数组,而原数组不变。函数的调用格式为:

     numpy.append(arr,values,axis)

其中,参数arr表示输入的数组;values表示向arr数组添加的元素,values为数组,values数组列维度与arr数组列维度相同;axis表示沿着水平或竖直方向完成添加操作的轴,axis取0表示沿竖直方向操作,axis取1表示沿水平方向操作。

如果未提供axis值,在添加操作之前输入数组会被展开,values可以是单元素,也可以是任意数组,将values添加到arr数组后,该函数会返回一个新数组,而原数组不变。

【例2-30】 利用numpy.append()函数实现在数组末尾添加元素。

     import numpy as np
     a=np.array([[1,0,3],[4,5,7]])
     print('第一个数组:')
     print(a)
     print('向数组添加元素:')
     print(np.append(a,[7,8,9]))
     print('沿轴0添加元素:')
     print(np.append(a,[[7,8,9]],axis=0))
     print('沿轴 1添加元素:')
     print(np.append(a,[[5,5,5],[7,8,9]],axis=1))

运行程序,输出如下。

     第一个数组:
     [[1 0 3]
      [4 5 7]]
     向数组添加元素:
     [1 0 3 4 5 7 7 8 9]
     沿轴0添加元素:
     [[1 0 3]
      [4 5 7]
      [7 8 9]]
     沿轴1添加元素:
     [[1 0 3 5 5 5]
      [4 5 7 7 8 9]]

2)numpy.insert()函数

numpy.insert()函数在给定索引之前,沿给定轴在输入数组中插入值。该函数会返回一个新数组,原数组不变。函数的调用格式为:

     numpy.insert(arr,obj,values,axis)

其中,参数arr表示输入的数组;obj表示在其之前插入值的索引;values表示向arr数组插入的值,values值可为单元素或values数组,并且values数组行维度与arr数组列维度相同;axis表示沿着水平或竖直方向完成插入操作的轴,axis取0表示沿竖直方向操作,即在arr数组行索引位于obj的位置处插入values值,axis取1表示沿水平方向操作,即在arr数组列索引位于obj的位置处插入values值。

如果未提供axis值,则在插入之前输入数组会被展开,values可以是单个元素,也可以是一维数组,将values插入obj的位置处,该函数会返回一个新数组,原数组不变。

另外,insert()函数如果传递了axis参数,则插入values值时,会以广播值数组作输入数组,即np.insert(arr,2,[9],axis=0),其中,values为[9],arr是2行4列数组,由于axis=0,则插入值的数组列维度与arr数组列维度相同,因此,插入值数组为1行4列的数组,也就是广播值数组[9,9,9,9]。

【例2-31】 利用numpy.insert()函数实现在数组中插入值。

     import numpy as np
     a=np.array([[1,4],[3,5],[5,8]])
     print('第一个数组:')
     print(a)
     print('未传递axis参数。在删除之前输入数组会被展开.')
     print(np.insert(a,3,[11,12]))
     print('传递了axis参数。会广播值数组来配输入数组.')
     print('沿轴0广播:')
     print(np.insert(a,1,[11],axis=0))
     print('沿轴 1广播:')
     print(np.insert(a,1,11,axis=  1))

运行程序,输出如下。

     第一个数组:
     [[1 4]
      [3 5]
      [5 8]]
     未传递axis参数。在删除之前输入数组会被展开.
     [1 4 3 11 12 5 5 8]
     传递了axis参数。会广播值数组来配输入数组.
     沿轴0广播:
     [[1 4]
      [11 11]
      [3 5]
      [5 8]]
     沿轴1广播:
     [[1 11 4]
      [3 11 5]
      [5 11 8]]

3)numpy.delete()函数

numpy.delete()函数返回从输入数组中删除指定子数组的新数组,原数组不变。与insert()函数的情况一样,如果未提供轴参数,则输入数组将展开。函数的格式为:

     numpy.delete(arr,obj,axis)

其中,参数arr表示输入的数组;obj是用整数或者整数数组表示的从输入数组中删除的子数组,obj可以用切片numpy.s_[start:end:step]表示要删除的子数组范围;axis表示沿着它删除给定子数组的轴,如果未提供axis值,则输入数组会被展开。

【例2-32】 利用numpy.delete()函数删除数组指定的子数组。

     import numpy as np
     a=np.arange(10).reshape(2,5)
     print('第一个数组:')
     print(a)
     print('未传递axis参数。在插入之前输入数组会被展开.')
     print(np.delete(a,5))
     print('删除第二列:')
     print(np.delete(a,1,axis=1))
     print('包含从数组中删除的替代值的切片:')
     a=np.array([1,2,3,4,5,6,7,8,9,10])
     print(np.delete(a,np.s_[::2]))

运行程序,输出如下。

     第一个数组:
     [[0 1 2 3 4]
      [5 6 7 8 9]]
     未传递axis参数。在插入之前输入数组会被展开。
     [0 1 2 3 4 6 7 8 9]
     删除第二列:
     [[0 2 3 4]
      [5 7 8 9]]
     包含从数组中删除的替代值的切片:
     [2 4 6 8 10]

4)numpy.unique()函数

numpy.unique()函数用于去除数组中的重复元素。函数的调用格式为:

     numpy.unique(arr,return_index,return_inverse,return_counts)

其中,arr为输入数组,如果不是一维数组则会展开;return_index如果为True,返回新列表元素在旧列表中的位置(下标),并以列表形式存储;return_inverse如果为True,返回旧列表元素在新列表中的位置(下标),并以列表形式存储;return_counts如果为True,返回去重数组中的元素在原数组中的出现次数。

【例2-33】 利用numpy.unique()函数去除数组中的重复元素。

     import numpy as np
     a=np.array([6,2,6,2,7,5,6,8,2,9])
     print('第一个数组:')
     print(a)
     print('第一个数组的去重值:')
     u=np.unique(a)
     print(u)
     print('去重数组的索引数组:')
     u,indices=np.unique(a,return_index=True)
     print(indices)
     print('我们可以看到每个和原数组下标对应的数值:')
     print(a)
     print('去重数组的下标:')
     u,indices=np.unique(a,return_inverse=True)
     print(u)
     print('下标为:')
     print(indices)
     print('使用下标重构原数组:')
     print(u[indices])
     print('返回去重元素的重复数量:')
     u,indices=np.unique(a,return_counts=True)
     print(u)
     print(indices)

运行程序,输出如下。 s1K8o3nSHT6SJm2Y17ogBpboyt5MGMx2yZY8NXyO/0ONFF1vqtjG6ZwYTiEUGjdf

     第一个数组:
     [6 2 6 2 7 5 6 8 2 9]
     第一个数组的去重值:
     [2 5 6 7 8 9]
     去重数组的索引数组:
     [1 5 0 4 7 9]
     我们可以看到每个和原数组下标对应的数值:
     [6 2 6 2 7 5 6 8 2 9]
     去重数组的下标:
     [2 5 6 7 8 9]
     下标为:
     [2 0 2 0 3 1 2 4 0 5]
     使用下标重构原数组:
     [6 2 6 2 7 5 6 8 2 9]
     返回去重元素的重复数量:
     [2 5 6 7 8 9]
     [3 1 3 1 1 1]
点击中间区域
呼出菜单
上一章
目录
下一章
×

打开