简介NumPy一个很重要的作用就是对多维数组进行运算。多维数组对象也称为ndarray。我们可以在ndarray的基础上进行一系列复杂的数学运算。本文将介绍一些基本的常用ndarray操作,您可以在数据分析中使用这些操作。创建ndarray创建ndarray的方法有很多种,我们可以使用np.random来随机生成数据:importnumpyasnp#Generatesomerandomdatadata=np.random.randn(2,3)dataarray([[0.0929,0.2817,0.769],[1.2464,1.0072,-1.2962]])除了随机创建,还可以从列表中创建:data1=[6,7.5,8,0,1]arr1=np.array(data1)array([6.,7.5,8.,0.,1.])从列表创建一个多维数组:data2=[[1,2,3,4],[5,6,7,8]]arr2=np.array(data2)array([[1,2,3,4],[5,6,7,8]])使用np.zeros创建一个初始值为0的数组:np.zeros(10)array([0.,0.,0.,0.,0.,0.,0.,0.,0.,0.])创建二维数组:np.zeros((3,6))array([[0.,0.,0.,0.,0.,0.],[0.,0.,0.,0.,0.,0.],[0.,0.,0.,0.,0.,0.]])使用空创建一个3D数组:np.empty((2,3,2))array([[[0.,0.],[0.,0.],[0.,0.]],[[0.,0.],[0.,0.],[0.,0.]]])注意这里我们看到数组的值empty创建的是0,不一定是thecase,empty会从内存中随机选择空格返回,并且不能保证这些空格中不会有值。所以我们在使用empty创建数组后,记得在使用前先初始化。使用arange创建范围类数组:np.arange(15)array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14])指定数组中元素的dtype:arr1=np.array([1,2,3],dtype=np.float64)arr2=np.array([1,2,3],dtype=np.int32)ndarray的属性可以通过data.shape获取数组的形状。data.shape(2,3)通过ndim获取维度信息:arr2.ndim2可以通过data.dtype获取具体的数据类型。data.dtypedtype('float64')ndarray中元素的类型转换创建一个ndarray类型后,也可以进行转换:arr=np.array([1,2,3,4,5])arr。dtypedtype('int64')float_arr=arr.astype(np.float64)float_arr.dtypedtype('float64')上面我们使用astype将int64类型的ndarray转为float64类型。如果转换类型的范围不匹配,将自动截断:arr=np.array([3.7,-1.2,-2.6,0.5,12.9,10.1])arr.astype(np.int32)array([3,-1,-2,0,12,10],dtype=int32)注意这里截去小数,没有四舍五入。ndarray的数学运算数组可以用常量运算也可以用数组运算:arr=np.array([[1.,2.,3.],[4.,5.,6.]])arr*arrarray([[1.,4.,9.],[16.,25.,36.]])arr+10array([[11.,12.,13.],[14.,15.,16.]])arr-arrarray([[0.,0.,0.],[0.,0.,0.]])1/arrarray([[1.,0.5,0.3333],[0.25,0.2,0.1667]])arr**0.5array([[1.,1.4142,1.7321],[2.,2.2361,2.4495]])数组也可以比较,比较数组中每个元素的大小:arr2=np.array([[0.,4.,1.],[7.,2.,12.]])arr2>arrarray([[False,True,False],[True,False,True]])索引的基本使用和slice首先看下index和slice的基本使用。Index的使用方式与普通数组基本相同,用于访问数组中的一个元素。需要注意的是,切片后返回的数组中的元素是对原数组中元素的引用,修改切片后的数组会影响原数组。#构建一维数组arr=np.arange(10)array([0,1,2,3,4,5,6,7,8,9])#索引访问arr[5]5#切片访问arr[5:8]array([5,6,7])#切片修改arr[5:8]=12array([0,1,2,3,4,12,12,12,8,9])#slice可以修改原数组的值arr_slice=arr[5:8]arr_slice[1]=12345arrarray([0,1,2,3,4,12,12345,12,8,9])#build二维数组arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])arr2d[2]array([7,8,9])#索引二维数组arr2d[0][2]3#索引二维数组arr2d[0,2]3#构建三维数组arr3d=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])arr3darray([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])#索引三维数组arr3d[0]array([[1,2,3],[4,5,6]])#复制是硬拷贝,原数组的值互不影响old_values=arr3d[0].copy()arr3d[0]=42arr3darray([[[42,42,42],[42,42,42]],[[7,8,9],[10,11,12]]])arr3d[0]=old_valuesarr3darray([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])#index三维数组arr3d[1,0]array([7,8,9])x=arr3d[1]xarray([[7,8,9],[10,11,12]])x[0]array([7,8,9])带切片的索引也可以作为索引使用,意思是一个索引范围值。索引表示的切片可以有多种形式。有头尾,表示索引从1开始到6-1结束:arr[1:6]array([1,2,3,4,64])没有头尾,它表示索引从0开始,到-1结束End:arr2d[:2]array([[1,2,3],[4,5,6]])有头无尾,表示从所有数据的开头和结尾:arr2d[:2,1:]array([[2,3],[5,6]])arr2d[1,:2]array([4,5])booleanindexindex也可以使用boolean值来表示是否选择该索引的数据。我们先看看如何构建一个boolean类型的数组:names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])names=='Bob'array([True,False,False,True,False,False,False])上面我们通过比较返回了一个只包含True和False的数组。这个数组可以作为索引值访问:#构建一个7*4数组data=np.random.randn(7,4)array([[0.275,0.2289,1.3529,0.8864],[-2.0016,-0.3718,1.669,-0.4386],[-0.5397,0.477,3.2489,-1.0212],[-0.5771,0.1241,0.3026,0.5238],[0.0009,1.3438,-0.7135,-0.860-02].,0.56015],[-1.265]0.1198,-1.0635,0.3329]])#通过布尔数组访问:data[names=='Bob']array([[0.275,0.2289,1.3529,0.8864],[-0.5771,0.1241,0.3026,0.5238]])When索引行,你也可以索引列:data[names=='Bob',3]array([0.8864,0.5238])你可以使用~符号来反转:data[~(names=='Bob')]array([[-2.0016,-0.3718,1.669,-0.4386],[-0.5397,0.477,3.2489,-1.0212],[0.0009,1.3438,-0.7135,-0.8312],[-2.3702,-1.8608,-0.86560,1],[-1.2659,0.1198,-1.0635,0.3329]])我们可以通过布尔数组来设置值,在实际项目中很有用:data[data<0]=0array([[0.275,0.2289,1.3529,0.8864],[0.,0.,1.669,0.],[0.,0.477,3.2489,0.],[0.,0.1241,0.3026,0.5238],[0.0009,1.3438,0.,0.],[0.,0.,0.,0.5601],[0.,0.1198,0.,0.3329]])data[names!='Joe']=7array([[7.,7.,7.,7.],[0.,0.,1.669,0.],[7.,7.,7.,7.],[7.,7.,7.,7.],[7.,7.,7.,7.],[0.,0.,0.,0.5601],[0.,0.1198,0.,0.3329]])FancyindexingFancyindexingFancyindexing也叫fancyindexing,指的是使用整型数组进行索引例如,我们首先创建一个8*4的数组:arr=np.empty((8,4))foriinrange(8):arr[i]=iarrarray([[0.,0.,0.,0.],[1.,1.,1.,1.],[2.,2.,2.,2.],[3.,3.,3.,3.],[4.,4.,4.,4.],[5.,5.,5.,5.],[6.,6.,6.,6.],[7.,7.,7.,7.]])然后用一个整型数组做索引,那么会按照指定的顺序选择行:arr[[4,3,0,6]]array([[4.,4.,4.,4.],[3.,3.,3.,3.],[0.,0.,0.,0.],[6.,6.,6.,6.]])负值进行索引:arr[[-3,-5,-7]]数组([[5.,5.,5.,5.],[3.,3.,3.,3.],[1.,1.,1.,1.]])花式索引也可以组合:arr=np.arange(32).reshape((8,4))arrarray([[0,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,31]])上面我们建了一个8*4的数组。arr[[1,5,7,2],[0,3,1,2]]array([4,23,29,10])然后取第二列的第一个值,第六列第三个的价值等等。最后得到一维数组。数组转换我们可以在不同维度的数组之间进行转换,也可以转换数组的轴。reshape方法可以将数组转换成任意形状:arr=np.arange(15).reshape((3,5))arrarray([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]])数组还提供了一个T命令来反转数组的轴:arr.Tarray([[0,5,10],[1,6,11],[2,7,12],[3,8,13],[4,9,14]])对于高维数组,可以使用transpose对坐标轴进行转置:arr=np.arange(16).reshape((2,2,4))arrarray([[[0,1,2,3],[4,5,6,7]],[[8,9,10,11],[12,13,14,15]]])arr.transpose((1,0,2))array([[[0,1,2,3],[8,9,10,11]],[[4,5,6,7],[12,13,14,15]]])如何理解上面的transpose((1,0,2))?它的意思是交换x轴和y轴,保持z轴不变。上面我们通过reshape((2,2,4))方法创建了一个3维的,也就是3轴的数组。它的形状是224。先看对应关系:(0,0)->[0,1,2,3](0,1)->[4,5,6,7](1,0)->[8,9,10,11](1,1)->[12,13,14,15]转换后:(0,0)->[0,1,2,3](0,1)->[8,9,10,11](1,0)-》[4,5,6,7](1,1)-》[12,13,14,15]于是我们得到了上面的结果。多维数组的坐标轴转换可能比较复杂,请多多理解。也可以使用swapaxes交换两个轴,上面的例子可以改写为:arr.swapaxes(0,1)本文已经收录在http://www.flydean.com/09-python-numpy-ndarray/解读,最深奥的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!
