NumPy——快速处理数据12NumPy—ndarray对象目录NumPy的导入创建数组存取元素多维数组结构数组3NumPy的导入标准的Python中用列表(list)保存一组值,可以当作数组使用。但由于列表的元素可以是任何对象,因此列表中保存的是对象的指针。对于数值运算来说,这种结构显然比较浪费内存和CPU计算Python提供了array模块,它和列表不同,能直接保存数值,但是由于它不支持多维数组,也没有各种运算函数,因此也不适合做数值运算。4NumPy的导入NumPy的诞生弥补了这些不足,NumPy提供了两种基本的对象:ndarray(n-dimensionalarrayobject)和ufunc(universalfunctionobject)。ndarray(下文统一称之为数组)是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。函数库的导入5importnumpyasnp创建数组在IPython中输入函数名并添加一个“?”符号,就可以显示文档内容。例如,输入“np.array?”可以通过给array函数传递Python的序列对象创建数组,如果传递的是多层嵌套的序列,将创建多维数组(下例中的变量c):6创建数组7a=np.array([1,2,3,4])b=np.array((5,6,7,8))c=np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]])barray([5,6,7,8])carray([[1,2,3,4],[4,5,6,7],[7,8,9,10]])c.dtype#数组的元素类型可以通过dtype属性获得dtype('int32')创建数组数组的大小可以通过其shape属性获得:可以通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度。8a.shape#一维数组(4,)c.shape#二维数组其中第0轴的长度为3,第1轴的长度为4。(3,4)c.shape=4,3#注意从(3,4)改为(4,3)并不是对数组进行转置,而只是改变每个轴的大小,数组元素在内存中的位置并没有改变:carray([[1,2,3],[4,4,5],[6,7,7],[8,9,10]])创建数组9d=a.reshape((2,2))#使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变。darray([[1,2],[3,4]])aarray([1,2,3,4])c.shape=2,-1#当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度,因此下面的程序将数组c的shape改为了(2,6)。carray([[1,2,3,4,4,5],[6,7,7,8,9,10]])创建数组数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组。10a[1]=100#将数组a的第一个元素改为100d#注意数组d中的2也被改变了array([[1,100],[3,4]])创建数组数组的元素类型可以通过dtype属性获得。可以通过dtype参数在创建时指定元素类型:11np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]],dtype=np.float)array([[1.,2.,3.,4.],[4.,5.,6.,7.],[7.,8.,9.,10.]])np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]],dtype=np.complex)array([[1.+0.j,2.+0.j,3.+0.j,4.+0.j],[4.+0.j,5.+0.j,6.+0.j,7.+0.j],[7.+0.j,8.+0.j,9.+0.j,10.+0.j]])创建数组上面的例子都是先创建一个Python序列,然后通过array函数将其转换为数组,这样做显然效率不高。因此NumPy提供了很多专门用来创建数组的函数。•arange函数类似于python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值:12np.arange(0,1,0.1)array([0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9])创建数组•linspace函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值:13np.linspace(0,1,10)#步长为1/9array([0.,0.11111111,0.22222222,0.33333333,0.44444444,0.55555556,0.66666667,0.77777778,0.88888889,1.])np.linspace(0,1,10,endpoint=False)#步长为1/10array([0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9])创建数组•logspace函数和linspace类似,不过它创建等比数列,下面的例子产生1(10^0)到100(10^2)、有20个元素的等比数列:14np.logspace(0,2,20)array([1.,1.27427499,1.62377674,2.06913808,2.6366509,3.35981829,4.2813324,5.45559478,6.95192796,8.8586679,11.28837892,14.38449888,18.32980711,23.35721469,29.76351442,37.92690191,48.32930239,61.58482111,78.47599704,100.])创建数组zeros()、ones()、empty()可以创建指定形状和类型的数组。此外,zeros_like()、ones_like()、empty_like()等函数可创建与参数数组的形状及类型相同的数组。因此,“zeros_like(a)”和“zeros(a.shape,a.dtype)”的效果相同。15np.empty((2,3),np.int)#只分配内存,不对其进行初始化array([[32571594,32635312,505219724],[45001384,1852386928,665972]])np.zeros(4,np.float)#元素类型默认为np.float,因此这里可以省略array([0.,0.,0.,0.])创建数组此外,使用frombuffer,fromstring,fromfile,fromfunction等函数可以从字节序列、文件创建数组,下面以fromfunction为例:np.fromfunction?fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape)。16deffunc(i):...returni%4+1...np.fromfunction(func,(10,))array([1.,2.,3.,4.,1.,2.,3.,4.,1.,2.])创建数组17下面的例子创建一个二维数组表示九九乘法表,输出的数组a中的每个元素a[i,j]都等于func2(i,j):deffunc2(i,j):...return(i+1)*(j+1)...a=np.fromfunction(func2,(9,9))aarray([[1.,2.,3.,4.,5.,6.,7.,8.,9.],[2.,4.,6.,8.,10.,12.,14.,16.,18.],[3.,6.,9.,12.,15.,18.,21.,24.,27.],[4.,8.,12.,16.,20.,24.,28.,32.,36.],[5.,10.,15.,20.,25.,30.,35.,40.,45.],[6.,12.,18.,24.,30.,36.,42.,48.,54.],[7.,14.,21.,28.,35.,42.,49.,56.,63.],[8.,16.,24.,32.,40.,48.,56.,64.,72.],[9.,18.,27.,36.,45.,54.,63.,72.,81.]])存取元素数组元素的存取方法和Python的标准方法相同:18a=np.arange(10)a[5]#用整数作为下标可以获取数组中的某个元素5a[3:5]#用范围作为下标获取数组的一个切片,包括a[3]不包括a[5]array([3,4])a[:5]#省略开始下标,表示从a[0]开始array([0,1,2,3,4])a[:-1]#下标可以使用负数,表示从数组后往前数array([0,1,2,3,4,5,6,7,8])a[2:4]=100,101#下标还可以用来修改元素的值aarray([0,1,100,101,4,5,6,7,8,9])a[1:-1:2]#范围中的第三个参数表示步长,2表示隔一个元素取一个元素存取元素19array([1,101,5,7])a[::-1]#省略范围的开始下标和结束下标,步长为-1,整个数组头尾颠倒array([9,8,7,6,5,4,101,100,1,0])a[5:1:-2]#步长为负数时,开始下标必须大于结束下标array([5,101])存取元素和Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间:20b=a[3:7]#通过下标范围产生一个新的数组b,b和a共享同一块数据空间barray([101,4,5,6])b[2]=-10#将b的第2个元素修改为-10barray([101,4,-10,6])a#a的第5个元素也被修改为10array([0,1,100,101,4,-10,6,7,8,9])存取元素除了使用下标范围存取元素之外,NumPy还提供了两种存取元素的高级方法。使用整数序列当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间。21x=np.arange(10,1,-1)xarray([10,9,8,7,6,5,4,3,2])存取元素22x[[3,3,1,8]]#获取x中的下标为3,3,1,8的4个元素,组成一个新的数组array([7,7,9,2])b=x[np.array([3,3,-3,8])]#下标可以是负数b[2]=100barray([7,7,100,2])x#由于b和x不共享数据空间,因此x中的值并没有改变array([10,9,8,7,6,5,4,3,2])x[[3,5,1]]=-1,-2,-3#整数序列下标也可以用来修改元素的值xarray([10,-3,8,-1,6,-2,4,3,2])存取元素使用布尔数组当使用布尔数组b作为下标存取数组x中的元素时,将收集数组x中所有在数组b中对应下标为True的元素。使用布尔数组作为下标获得的数组不和原始数组共享数据空间,注意这种方式只对应于布尔数组,不能使用布尔列表。23x=np.arange(5,0,-1)xarray([5,4,3,2,1])存取元素24x[np.array([True,False,True,False,False])]#布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素array([5,3])x[[True,False,True,False,False]]#如果是布尔列表,则把True当作1,False当