NumPy(Numerical Python)是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外,也针对数组运算提供大量的数学函数库。NumPy对于scikit-learn来说是至关重要的,因为scikit-learn使用NumPy数组形式的数据来进行处理,所以需要把数据都转换成NumPy数组的形式,而多维数组也是NumPy的核心功能之一。
NumPy是一个运行速度非常快的数学库,主要用于数组计算,包含:
(1)一个强大的N维数组对象ndarray。
(2)广播功能函数。
(3)整合C/C++/FORTRAN代码的工具。
(4)线性代数、傅里叶变换、随机数生成等功能。
NumPy数组是一个多维数组,称为ndarray。NumPy的创建方法有以下三种,分别为:用特殊函数创建、从已有的数组创建数组以及从数值范围创建数组。
注意: 在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]])
除了可以利用函数创建特殊数组外,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.]
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.]
NumPy中包含一些函数用于处理数组,大概可分为以下几类:修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除等。
在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]
数组的翻转也是数组比较重要的操作之一,属于形状变化或维度变化的操作。可以通过以下方法实现,这些方法有属于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))
在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)
连接意味着将两个或多个数组的内容放在单个数组中。在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()
运行程序,输出如下。
在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]])]
在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)
运行程序,输出如下。
第一个数组: [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]