第3章NumPy数值计算基础 NumPy是在1995年诞生的Python库Numeric的基础上建立起来的,但真正促使NumPy发行的是Python的SciPy库。SciPy是2001年发行的一个类似于MATLAB、Maple和Mathematica等数学计算软件的Python库,它可以实现数值计算中的大多数功能,但SciPy中并没有合适的类似于Numeric中的对于基础数据对象处理的功能。于是,SciPy的开发者将SciPy中的一部分和Numeric的设计思想结合,在2005年发行了NumPy。 NumPy是Python的一种开源的数值计算扩展库。它包含很多功能,如创建n维数组(矩阵)、对数组进行函数运算、数值积分、线性代数运算、傅里叶变换和随机数产生等。 标准的Python用List(列表)保存值,可以当作数组使用,但因为列表中的元素可以是任何对象,所以浪费了CPU运算的时间和内存。NumPy的诞生弥补了这些缺陷,它提供了两种基本的对象。  ndarray(ndimensional array object): 是存储单一数据类型的多维数组;  ufunc(universal function object): 是一种能够对数组进行处理的函数。 NumPy常用的导入格式: import numpy as np 导入NumPy后,可通过np.+Tab键查看可使用的函数。如果对其中一些函数的使用不是很清楚,可以在对应的函数名后+?(如np.abs?)运行,可以方便地查看相应函数的帮助信息。 视频讲解 3.1NumPy多维数组 3.1.1创建数组对象 通过NumPy库的array函数可以创建ndarray数组。通常来说,ndarray是一个通用的同构数据容器,即其中的所有元素都需要相同的类型。NumPy库能将数据(列表、元组、数组或其他序列类型)转换为ndarray数组。 1. 使用array函数创建数组对象 array函数的格式: np.array(object, dtype,ndmin) array函数的主要参数及其使用说明见表31。 表31array函数的主要参数及其说明 参数说明 object 接收array,表示想要创建的数组 dtype 接收datatype,表示数组所需的数据类型,未给定则选择保存对象所需的最小类型,默认为Nonendmin 接收int,指定生成数组应该具有的最小维数,默认为None 【例31】创建ndarray数组。 In[1]: import numpy as np data1 = [1,3,5,7]#列表 w1 = np.array(data1) print('w1:',w1) data2 = (2,4,6,8)#元组 w2 = np.array(data2) print('w2:',w2) data3 = [[1,2,3,4],[5,6,7,8]]#多维数组 w3 = np.array(data3) print('w3:',w3) Out[1]: w1: [1 3 5 7] w2: [2 4 6 8] w3: [[1 2 3 4] [5 6 7 8]] 在创建数组时,NumPy会为新建的数组推断出一个合适的数据类型,并保存在dtype中,当序列中有整数和浮点数时,NumPy会把数组的dtype定义为浮点数据类型。 【例32】在array函数中指定dtype。 In[2]:w3 = np.array([1,2,3,4],dtype = 'float64') print(w3.dtype) Out[2]:float64 2. 专门创建数组的函数 通过array函数使用已有的Python序列创建数组效率不高,因此,NumPy提供了很多专门创建数组的函数。 1) arange函数 arange函数类似于Python的内置函数range,但是arange主要用来创建数组。 【例33】使用arange创建数组。 In[3]: warray = np.arange(10) print(warray) Out[3]:[0 1 2 3 4 5 6 7 8 9] arange函数可以通过指定起始值、终值和步长创建一维数组,创建的数组不包含终值。 【例34】指定起始值、终值及步长参数的arange。 In[4]:warray = np.arange(0,1,0.2) print(warray) Out[4]:[0. 0.2 0.4 0.6 0.8] 2) linspace函数 当 arange 的参数是浮点型时,由于浮点的精度有限,通常不太可能去预测获得元素的数量。出于这个原因,通常选择更好的函数linspace,它接收元素数量作为参数。linspace函数通过指定起始值、终值和元素个数创建一维数组,默认包括终值。 【例35】使用linspace函数创建数组。 In[5]:warray = np.linspace(0,1,5) print(warray) Out[5]:[0. 0.25 0.5 0.75 1. ] 3) logspace函数 logspace函数和linspace函数类似,不同点是它所创建的是等比数列。 【例36】使用logspace函数创建数组。 In[6]:warray = np.logspace(0,1,5) #生成1~10的具有5个元素的等比数列 print(warray) Out[6]:[1. 1.77827941 3.16227766 5.62341325?10.] logspace的参数中,起始位和终止位代表的是10的幂(默认基数为10),第三个参数表示元素个数。 4) zeros函数 zeros函数可以创建指定长度或形状的全0数组。 【例37】使用zeros函数创建全零矩阵。 In[7]:print(np.zeros(4)) print(np.zeros([3,3])) Out[7]: [0. 0. 0. 0.] [[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]] 5) ones函数 ones函数可以创建指定长度或形状的全1数组。 【例38】使用ones函数创建全1数组。 In[8]:print(np.ones(5)) print(np.ones([2,3])) Out[8]:[1. 1. 1. 1. 1.] [[1. 1. 1.] [1. 1. 1.]] 6) diag函数 diag函数可以创建对角矩阵,即对角线元素为0或指定值,其他元素为0。 【例39】使用diag函数创建对角矩阵。 In[9]:print(np.diag([1,2,3,4])) Out[9]: [[1 0 0 0] [0 2 0 0] [0 0 3 0] [0 0 0 4]] 此外,使用eye函数可创建一条对角线位置为1、其他位置全为 0 的矩阵。 3.1.2ndarray对象属性和数据转换 NumPy创建的ndarray对象属性主要有shape、size等属性,具体见表32。 表32ndarray对象属性及其说明 属性说明 ndim 秩,即数据轴的个数 shape 数组的维度 size 数组元素个数 dtype 数据类型 itemsize 数组中每个元素的字节大小 【例310】查看数组的属性。 In[10]:warray = np.array([[1,2,3],[4,5,6]]) print('秩为:',warray.ndim) print('形状为:',warray.shape) print('元素个数为:',warray.size) Out[10]: 秩为: 2 形状为: (2, 3) 元素个数为: 6 数组的shape可以重新设置。 【例311】设置数组的shape属性。 In[11]:warray.shape = 3,2 print(warray) Out[11]:[[1 2] [3 4] [5 6]] 对于创建好的数组ndarray,可以通过astype方法进行数据类型的转换。 【例312】数组的类型转换。 In[12]:arr1 = np.arange(6) print(arr1.dtype) arr2 = arr1.astype(np.float64) print(arr2.dtype) Out[12]:int32 float64 3.1.3生成随机数 在NumPy.random模块中,提供了多种随机数的生成函数,例如randint可以生成指定范围的随机整数。 用法: np.random.randint(low,high = None,size = None) 【例313】生成随机整数。 In[13]: arr = np.random.randint(100,200,size = (2,4)) print(arr) Out[13]:[[197 129 112 153] [138 195 114 141]] 【例314】生成[0,1]的随机数组。 In[14]:arr1 = np.random.rand(5) print(arr1) arr2 = np.random.rand(4,2) print(arr2) Out[14]: [0.13654637 0.09218044 0.44985683 0.24374376 0.60841164] [[0.07250518 0.50867613] [0.21831215 0.23476073] [0.81293096 0.92887008] [0.28339637 0.82806109]] 注意: 因为是随机数,每次运行代码生成的随机数组都不一样。为了每次生成同一份数据,可以指定一个随机种子,然后使用shuffle函数打乱生成的随机数。表33列出了random模块常用的随机数生成方法。 表33random模块常用的随机数生成函数 函数 说明 seed 确定随机数生成器的种子 permutation 返回一个序列的随机排列或返回一个随机排列的范围 shuffle 对一个序列进行随机排序 binomial 产生二项分布的随机数 normal 产生正态(高斯)分布的随机数 beta 产生beta分布的随机数 chisquare 产生卡方分布的随机数 gamma 产生gamma分布的随机数 uniform 产生在[0,1)中均匀分布的随机数 3.1.4数组变换 1. 数组重塑 对于定义好的数组,可以通过reshape方法改变其数组维度,传入的参数为新维度的元组。 【例315】改变数组维度。 In[15]:arr1 = np.arange(8) print(arr1) arr2=arr1.reshape(4,2) print(arr1) Out[15]:[0 1 2 3 4 5 6 7] [[0 1] [2 3] [4 5] [6 7]] reshape中的一个参数可以设置为-1,表示数组的维度可以通过数据本身来推断。 【例316】reshape的一个维度设置为-1。 In[16]: arr1 = np.arange(12) print('arr1:',arr1) arr2 = arr1.reshape(2,-1) print('arr2:',arr2) Out[16]:arr1: [ 0 1 2 3 4 5 6 7 8 9 10 11] arr2: [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11]] 与reshape相反的方法是数据散开(ravel)或数据扁平化(flatten)。 【例317】数据散开。 In[17]: arr1 = np.arange(12).reshape(3,4) print('arr1:',arr1) arr2 = arr1.ravel() print('arr2:',arr2) Out[17]: arr1: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] arr2: [ 0 1 2 3 4 5 6 7 8 9 10 11] 需要注意的是,数据重塑不会改变原来的数组。 2. 数组合并 数组合并用于多个数组间的操作,NumPy使用hstack、vstack和concatenate函数完成数组的合并。 横向合并是将ndarray对象构成的元组作为参数,传给hstack函数。 【例318】两个数组的横向合并。 In[18]: arr1 = np.arange(6).reshape(3,2) arr2 = arr1*2 arr3 = np.hstack((arr1,arr2)) print(arr3) Out[18]: [[ 0 1 0 2] [ 2 3 4 6] [ 4 5 8 10]] 纵向合并是使用vstack将数组纵向合并。 【例319】数组纵向合并。 In[19]: arr1 = np.arange(6).reshape(3,2) arr2 = arr1*2 arr3 = np.vstack((arr1,arr2)) print(arr3) Out[19]:[[ 0 1] [ 2 3] [ 4 5] [ 0 2] [ 4 6] [ 8 10]] concatenate函数可以实现数组的横向合并或纵向合并,其中的参数axis=1时进行横向合并,axis=0时进行纵向合并。 【例320】使用concatenate函数合并数组。 In[20]: arr1 = np.arange(6).reshape(3,2) arr2 = arr1*2 print('横向合并为:',np.concatenate((arr1,arr2),axis = 1)) print('纵向合并为:',np.concatenate((arr1,arr2),axis = 0)) Out[20]: 横向合并为: [[ 0 1 0 2] [ 2 3 4 6] [ 4 5 8 10]] 纵向合并为: [[ 0 1] [ 2 3] [ 4 5] [ 0 2] [ 4 6] [ 8 10]] 3. 数组分割 与数组合并相反,NumPy提供了hsplit、vsplit和split分别实现数组的横向、纵向和指定方向的分割。 【例321】数组的分割。 In[21]: arr = np.arange(16).reshape(4,4) print('横向分割为:\n',np.hsplit(arr,2)) print('纵向组合为:\n',np.vsplit(arr,2)) Out[21]: 横向分割为: [array([[ 0, 1], [ 4, 5], [ 8, 9], [12, 13]]), array([[ 2, 3], [ 6, 7], [10, 11], [14, 15]])] 纵向组合为: [array([[0, 1, 2, 3], [4, 5, 6, 7]]), array([[ 8, 9, 10, 11], [12, 13, 14, 15]])] 同样,split在参数axis=1时实现数组的横向分割,axis=0时则进行纵向分割。 4. 数组转置和轴对换 数组转置是数组重塑的一种特殊形式,可以通过transpose方法进行转置。transpose方法需要传入轴编号组成的元组。 【例322】数组使用transpose转置。 In[22]: arr = np.arange(6).reshape(3,2) print('矩阵:',arr) print('转置矩阵:',arr.transpose((1,0))) Out[22]:矩阵: [[0 1] [2 3] [4 5]] 转置矩阵: [[0 2 4] [1 3 5]] 除了使用transpose外,可以直接使用数组的T属性进行数组转置。 【例323】数组的T属性转置。 In[23]: print(arr.T) Out[23]: [[0 2 4] [1 3 5]] ndarray的swapaxes方法实现轴对换。 【例324】数组的轴对换。 In[24]: arr = np.arange(6).reshape(3,2) print(arr) print(arr.swapaxes(0,1)) Out[24]:[[0 1] [2 3] [4 5]] [[0 2 4] [1 3 5]] 视频讲解 3.2数组的索引和切片 在数据分析中经常会选取符合条件的数据,NumPy中通过数组的索引和切片进行数组元素的选取。 3.2.1一维数组的索引 一维数组的索引类似于Python中的列表。 【例325】一维数组的索引。 In[25]: arr = np.arange(10) print(arr) print(arr[2]) print(arr[-1]) print(arr[1:4]) Out[25]: [0 1 2 3 4 5 6 7 8 9] 2 9 [1 2 3] 数组的切片返回的是原始数组的视图,并不会产生新的数据,这就意味着在视图上的操作会使原数组发生改变。如果需要的并非视图而是要复制数据,则可以通过copy方法实现。 【例326】数组元素的复制。 In[26]: arr1 = arr[-4:-1].copy() print(arr) print(arr1) Out[26]: [0 1 2 3 4 5 6 7 8 9] [6 7 8] 3.2.2多维数组的索引 对于多维数组,它的每一个维度都有一个索引,各个维度的索引之间用逗号分隔。 【例327】多维数组的索引。 In[27]: arr = np.arange(12).reshape(3,4) print(arr) print(arr[0,1:3])#索引第0行中第1列到第2列的元素 print(arr[:,2])#索引第2列元素 print(arr[:1,:1])#第0行第0列元素 Out[27]:[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [1 2] [ 2 6 10] [[0]] 也可以使用整数函数和布尔值索引访问多维数组。 【例328】访问多维数组。 In[28]: arr = np.arange(12).reshape(3,4) #从两个序列的对应位置取出两个整数来组成下标:arr[0,1],arr[1,3] print(arr) print('索引结果1:',arr[(0,1),(1,3)]) #索引第1行中第0、2、3列的元素 print('索引结果2:',arr[1:2,(0,2,3)]) mask = np.array([1,0,1],dtype = np.bool) #mask是一个布尔数组,它索引第0、2行中第1列元素 print('索引结果3:',arr[mask,1]) Out[28]: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] 索引结果1: [1 7] 索引结果2: [[4 6 7]] 索引结果3: [1 9] 视频讲解 3.3数组的运算 数组的运算支持向量化运算,将本来需要在Python级别进行的运算放到C语言的运算中,会明显地提高程序的运算速度。 3.3.1数组和标量间的运算 数组之所以很强大是因为不需要通过循环就可以完成批量计算,例如相同维度的数组的算术运算直接应用到元素中。 【例329】数组元素的追加。 In[29]: a = [1,2,3] b = [] for i in a: b.append(i*i) print('b数组:',b) wy = np.array([1,2,3]) c = wy*2 print('c数组:',c) Out[29]: b数组: [1, 4, 9] c数组: [2 4 6] 3.3.2ufunc函数 ufunc函数全称为通用函数,是一种能够对数组中的所有元素进行操作的函数。ufunc函数针对数组进行操作,而且以NumPy数组作为输出。对一个数组进行重复运算时,使用ufunc函数比使用math库中的函数效率要高很多。 1. 常用的ufunc函数运算 常用的ufunc函数运算有四则运算、比较运算和逻辑运算。 (1) 四则运算: 加(+)、减(-)、乘(*)、除(/)、幂(**)。数组间的四则运算表示对每个数组中的元素分别进行四则运算,所以形状必须相同。 (2) 比较运算: >、<、==、>=、<=、!=。比较运算返回的结果是一个布尔数组,每个元素为每个数组对应元素的比较结果。 (3) 逻辑运算: np.any函数表示逻辑“or”; np.all函数表示逻辑“and”,运算结果返回布尔值。 【例330】数组的四则运算。 In[30]: x = np.array([1,2,3]) y = np.array([4,5,6]) print('数组相加结果:',x+y) print('数组相减结果:',x-y) print('数组相乘结果:',x*y) print('数组幂运算结果:',x**y) Out[30]:数组相加结果: [5 7 9] 数组相减结果: [-3 -3 -3] 数组相乘结果: [ 4 10 18] 数组幂运算结果: [ 1 32 729] ufunc也可以进行比较运算,返回的结果是一个布尔数组,其中每个元素都是对应元素的比较结果。 【例331】数组的比较运算。 In[31]: x = np.array([1,3,6]) y = np.array([2,3,4]) print('比较结果(<):',x):',x>y) print('比较结果(==):',x==y) print('比较结果(>=):',x>=y) print('比较结果(!=):',x!=y) Out[31]: 比较结果(<): [ True False False] 比较结果(>): [False False True] 比较结果(==): [False True False] 比较结果(>=): [False True True] 比较结果(!=): [ True False True] 2. ufunc函数的广播机制 广播(broadcasting)是指不同形状的数组之间执行算术运算的方式。广播机制需要遵循4个原则: (1) 让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分都通过在前面加1补齐。 (2) 输出数组的shape是输入数组shape的各个轴上的最大值。 (3) 如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错。 (4) 当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值。 【例332】ufunc函数的广播。 In[32]: arr1 = np.array([[0,0,0],[1,1,1],[2,2,2]]) arr2 = np.array([1,2,3]) print('arr1:\n',arr1) print('arr2:\n',arr2) print('arr1+arr2:\n',arr1+arr2) Out[32]: arr1: [[0 0 0] [1 1 1] [2 2 2]] arr2: [1 2 3] arr1+arr2: [[1 2 3] [2 3 4] [3 4 5]] 3.3.3条件逻辑运算 在NumPy中可以使用基本的逻辑运算实现数组的条件运算。 【例333】数组的逻辑运算。 In[33]: arr1 = np.array([1,3,5,7]) arr2 = np.array([2,4,6,8]) cond = np.array([True,False,True,False]) result = [(x if c else y)for x,y,c in zip(arr1,arr2,cond)] result Out[33]:[1, 4, 5, 8] 但这种方法对大规模数组处理效率不高,也无法用于多维数组。NumPy提供的where方法可以克服这些问题。 where的用法: np.where(condition, x,y) 如果满足条件(condition)输出x; 不满足则输出y。 【例334】where的基本用法。 In[34]: np.where([[True,False], [True,True]],[[1,2], [3,4]],[[9,8], [7,6]]) Out[34]:array([[1, 8],[3, 4]]) 在这个例子中条件为[[True,False], [True,True]],分别对应最后输出结果的4个值,运算时第一个值从[1,9]中选,因为条件为True,所以选1; 第二个值从[2,8]中选,因为条件为False,所以选8,后面以此类推。 【例335】where中只有condition参数。 In[35]: w = np.array([2,5,6,3,10]) np.where(w>4) Out[35]:(array([1, 2, 4], dtype=int64),) where中若只有条件 (condition),没有x和y,则输出满足条件元素的坐标。这里的坐标以tuple的形式给出,通常原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。 3.4数组读/写 3.4.1读/写二进制文件 NumPy提供了多种文件操作函数存取数组内容。文件存取的格式分为两类: 二进制和文本。二进制格式的文件又分为NumPy专用的格式化二进制类型和无格式类型。NumPy中读/写二进制文件的方法有以下两种。 (1) NumPy.load("文件名.npy"): 从二进制的文件中读取数据。 (2) NumPy.save("文件名[.npy]",arr): 以二进制的格式保存数据。 它们会自动处理元素类型和shape等信息,使用它们读/写数组就非常方便。但是np.save输出的文件很难用其他语言编写的程序读入。 【例336】数组的读/写。 In[36]: a = np.arange(1,13).reshape(3,4) print(a) np.save('arr.npy', a) # np.save("arr", a) c = np.load( 'arr.npy' ) print(c) Out[36]:[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] 【例337】多个数组保存。 In[37]: a = np.array([[1,2,3],[4,5,6]]) b = np.arange(0, 1.0, 0.1) c = np.sin(b)#长度为10 print(c) np.savez('result.npz', a, b, sin_array = c) r = np.load('result.npz') r['arr_0']#数组a Out[37]: [0.0.09983342 0.19866933 0.29552021 0.38941834 0.47942554 0.56464247 0.64421769 0.71735609 0.78332691] array([[1, 2, 3], [4, 5, 6]]) 3.4.2读/写文本文件 NumPy中读/写文本文件的主要方法有以下几种。 (1) NumPy.loadtxt("../tmp/arr.txt",delimiter=","): 把文件加载到一个二维数组中。 (2) NumPy.savetxt("../tmp/arr.txt",arr,fmt="%d",delimiter=","): 将数组写到某种分隔符隔开的文本文件中。 (3) NumPy.genfromtxt("../tmp/arr.txt", delimiter=","): 结构化数组和缺失数据。 【例338】读/写文本文件。 In[38]: a = np.arange(0,12,0.5).reshape(4,-1) np.savetxt("a1-out.txt", a) #默认按照'%.18e'格式保存数值 np.loadtxt("a1-out.txt") np.savetxt("a2-out.txt", a, fmt = "%d", delimiter = ",") #改为保存为整数,以逗号分隔 np.loadtxt("a2-out.txt",delimiter = ",") # 读入的时候也需要指定逗号分隔 Out[38]:array([[ 0., 0., 1., 1., 2., 2.], [ 3., 3., 4., 4., 5., 5.], [ 6., 6., 7., 7., 8., 8.], [ 9., 9., 10., 10., 11., 11.]]) 3.4.3读取CSV文件 读取CSV文件格式: loadtxt(fname, dtype=, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding='bytes') 主要参数及其说明见表34。 表34主要参数及其说明 参数说明 fname str,读取的CSV文件名 delimiter str,数据的分隔符 usecols tuple(元组) ,执行加载数据文件中的哪些列 unpack bool,是否将加载的数据拆分为多个组,True表示拆,False表示不拆 skiprows int,跳过多少行,一般用于跳过前几行的描述性文字 encoding bytes,编码格式 视频讲解 3.5NumPy中的数据统计与分析 在NumPy中,数组运算更为简捷而快速,通常比等价的Python方式快很多,尤其在处理数组统计计算与分析的 情况下。 3.5.1排序 NumPy的排序方式有直接排序和间接排序。直接排序是对数据直接进行排序,间接排序是指根据一个或多个键值对数据集进行排序。在NumPy中,直接排序经常使用sort函数,间接排序经常使用argsort函数和lexsort函数。 sort函数是最常用的排序方法,函数调用改变原始数组,无返回值。 格式: numpy.sort(a,axis,kind,order) 主要参数及其说明见表35。 表35sort主要参数及其说明 参数说明 a要排序的数组 axis 使得sort函数可以沿着指定轴对数据集进行排序。axis=1为沿横轴排序; axis=0为沿纵轴排序; axis=None,将数组平坦化之后进行排序 kind 排序算法,默认为quicksort order 如果数组包含字段,则是要排序的字段 【例339】使用sort函数进行排序。 In[39]: arr = np.array([7,9,5,2,9,4,3,1,4,3]) print('原数组:',arr) arr.sort() print('排序后:',arr) Out[39]: 原数组: [7 9 5 2 9 4 3 1 4 3] 排序后: [1 2 3 3 4 4 5 7 9 9] 【例340】带轴向参数的sort排序。 In[40]: arr = np.array([[4,2,9,5],[6,4,8,3],[1,6,2,4]]) print('原数组:\n',arr) arr.sort(axis = 1) #沿横向排序 print('横向排序后:\n',arr) Out[40]: 原数组: [[4 2 9 5] [6 4 8 3] [1 6 2 4]] 横向排序后: [[2 4 5 9] [3 4 6 8] [1 2 4 6]] 使用argsort和lexsort函数,可以在给定一个或多个键时,得到一个由整数构成的索引数组,索引值表示数据在新的序列中的位置。 【例341】使用argsort函数进行排序示例。 In[41]arr = np.array([7,9,5,2,9,4,3,1,4,3]) print('原数组:',arr) print('排序后:',arr.argsort()) #返回值为数组排序后的下标排列 print('显示较大的5个数:',arr[arr.argsort()][-5:]) Out[41]原数组: [7 9 5 2 9 4 3 1 4 3] 排序后: [7 3 6 9 5 8 2 0 1 4] 显示较大的5个数: [4 5 7 9 9] 【例342】使用lexsort排序示例。 In[42]a = [1,5,7,2,3,-2,4] b = [9,5,2,0,6,8,7] ind=np.lexsort((b,a)) print('ind:',ind) tmp=[(a[i],b[i])for i in ind] print('tmp:',tmp) Out[42]ind: [5 0 3 4 6 1 2] tmp: [(-2, 8), (1, 9), (2, 0), (3, 6), (4, 7), (5, 5), (7, 2)] 3.5.2重复数据与去重 在数据统计分析中,需要提前将重复数据剔除。在NumPy中,可以通过unique函数找到数组中的唯一值并返回已排序的结果,其中的参数return_counts设置为True时可以返回每个取值出现的次数。 【例343】数组内数据去重。 In[43]names = np.array(['红色','蓝色','蓝色','白色','红色','红色']) print('原数组:',names) print('去重后的数组:',np.unique(names)) print('数据出现次数:',np.unique(names,return_counts=True)) Out[43]原数组: ['红色' '蓝色' '蓝色' '白色' '红色' '红色'] 去重后的数组: ['白色' '红色' '蓝色'] 数据出现次数: (array(['白色', '红色', '蓝色'], dtype='