第3章〓Python数据挖掘中的常用模块 Python具有强大的扩展能力,其中的数据分析与挖掘常用模块几乎可以满足人们的各种需求。例如,科学计算模块NumPy提供了矩阵运算; 基于NumPy的数据分析处理模块Pandas提供了一些数据挖掘工具; 数据可视化模块Matplotlib具有类似MATLAB的绘图工具; 针对Python编程软件免费版的机器学习模块Scikitlearn具有常用的分类、回归和聚类等算法。 3.1NumPy模块 NumPy(Numerical Python的简称)是Python的一个开源数值计算扩展模块,可以用来存储和处理大型矩阵。NumPy要比Python自身的嵌套列表结构高效得多,支持大维度数组与矩阵运算,并且针对数组运算提供了大量的数学函数库。 3.1.1NumPy数据类型 NumPy提供了一个n维数组类型ndarray,描述了相同类型的“items”的集合。n维数组(ndarray)是NumPy主要的数据类型,数组的下标从0开始。 1. ndarray对象 ndarray对象可以通过一个常规的Python列表或者使用array()函数的元组来构建,通过调用生成后数组的dtype属性来了解该数组的元素类型。 导入NumPy库的语句形式主要有以下3种。  import numpy as np: 在这个方式下使用NumPy函数或属性时以np.开头。  import numpy: 在这个方式下使用NumPy函数或属性时以numpy.开头。  from numpy import *: 在这个方式下使用NumPy函数或属性时可以直接引用。 一般常用第一种方法,尽量不用第三种方法。以后如果没有特殊说明,都是默认使用第一种方法。 (1) 利用列表创建数组,其常用形式为np.array(object[,dtype][,ndmin])。 参数说明: ① object为同类型元素的列表或元组。 ② dtype表示数组所需的数据类型,默认为None。 ③ ndmin为int类型,指定生成数组应该具有的最小维数,默认为None。 例3.1用列表生成数组示例。 程序代码如下: import numpy as np data=[3,-4,7,12] x=np.array(data) #使用列表生成一维数组 print(x) data=[[1,2],[3,4],[5,6]] y=np.array(data) #使用列表生成二维数组 print(y) (2) 利用range()和arange()函数生成一维数组,其常用形式如下。 ① range(start,end,step): 返回一个list对象,起始值为start,终止值为end,但不含终止值,步长为step。该函数只能创建int型list。 ② arange(start,end,step): 与range()类似,但是返回一个ndarray对象,并且可以使用float型数据。 (3) 利用arange()函数和reshape()函数创建多维数组,其常用形式为: np.arange().reshape(,,…,) 说明: 该方法利用arange()函数生成一维数组,而利用reshape()函数将一维数组转换为多维数组。 例3.2创建数组示例。 程序代码如下: import numpy as np a=np.arange(0,1,0.1) #生成一维数组 print(a) b=np.arange(10).reshape(2,5) #生成2×5数组 print(b) 2. matrix对象 matrix是ndarray的一个小分支,它拥有ndarray的所有特性。在NumPy中matrix的主要优势是具有简单的乘法运算符号。例如a和b是两个matrix类型的对象,则a*b就是矩阵积。 利用mat()函数或matrix()函数可以创建矩阵,其常用形式为np.mat|matrix(),其中可以是①字符串,例如np.mat('1 2 3; 4 5 3'); ②嵌套列表,例如np.mat([[1,5,10],[1.5,6,14]]); ③数组,例如np.mat(np.random.rand(3,4))。 以下是创建矩阵的常见例句。 data1=np.mat(np.zeros((3,3))): 创建一个3×3的零矩阵,其中zeros()函数的参数是一个tuple类型。 data2= np.mat(np.ones((2,4))): 创建一个2×4的元素为1的矩阵,默认是浮点型的数据,如果需要是int类型,可以使用dtype=int。 data3=np.mat(np.random.rand(2,2)): 其中random使用的是NumPy中的random模块,random.rand(2,2)创建的是一个二维数组,需要将其转换成matrix类型。 data4=np.mat(np.random.randint(10,size=(3,3))): 生成一个3×3的0~10的随机整数矩阵,如果需要指定下界,则可以多加一个参数。 data5=np.mat(np.random.randint(2,8,size=(2,5))): 产生一个2~8的随机整数矩阵。 data6=np.mat(np.diag([1,2,3])): 生成一个对角线元素为1、2、3的对角矩阵。 3. Python列表与NumPy数组的区别 虽然Python列表与NumPy数组在形式和应用上类似,但是它们之间有着本质的区别,在数据科学领域中应用NumPy多维数组要比应用Python列表更有效。NumPy数组也支持“向量化”操作,可以有效地处理大型稀疏数据集。 Python列表与NumPy数组的区别如下: (1) Python列表不需要指定长度、数据类型,可以进行索引、更新、删除、切片等操作,但创建NumPy数组时必须指定数组长度和数据类型。 (2) 列表是Python中内置的数据类型,使用方括号[]和逗号分隔符,其元素的类型可以不同,但NumPy数组中元素的类型必须相同。 (3) Python列表中所有元素的内存地址可以不是连续的,它是通过每个元素记录上一个元素的内存地址和下一个元素的内存地址来排列的,而NumPy数组是一个连续的内存空间,每个元素都按照先后顺序排列在内存中,所以存放数据还是尽量使用数组。 (4) Python列表中有append的方法,可以进行追加,而NumPy数组没有类似的方法。 (5) 用print()函数打印的结果不同,Python列表元素之间用逗号分隔,而NumPy数组元素之间用空格分隔。 3.1.2NumPy基本运算 NumPy提供了一些用于算术运算的方法,使用起来会比Python提供的运算符灵活一些。 1. ndarray对象的基本运算 NumPy基本运算都是按元素操作的,下面给出一些基本运算。 假设a=np.arange(3,11,2),b=np.array([1,4,3,2]),ndarray对象的基本运算如表3.1所示。 表3.1ndarray对象的基本运算 运算符说明示例结果 +加法a+b[ 49 10 11] -减法a-b[2 1 4 7] *乘法a*b,3*a[ 3 20 21 18],[ 9 15 21 27] /除法a/b[3. 1.252.33333333 4.5 ] %取余数b%a[0 1 1 1] **幂运算a**3[ 27 125 343 729] 例3.3多维数组基本运算示例。 程序代码如下: import numpy as np a=np.array([[1,2,3],[3,4,1]]) b=np.arange(6).reshape(2,3) print(a,'\n',b) print(a+b) print(a-b) print(a*b) print(a**3) print(2*a) dot()函数返回的是两个数组(向量)的点积(dot product)。 例3.4数组对象乘法和点积运算示例。 程序代码如下: import numpy as np a=np.array([0,1,2,3]) b=np.array([2,1,3,-2]) c=np.array([[4,3],[2,1]]) d=np.array([[1,2],[3,4]]) print('一维数组乘法: ',a*b) print('一维数组点积: ',np.dot(a,b)) print('二维数组乘法: \n',c*d) print('二维数组点积: \n',np.dot(c,d)) 2. matrix对象的基本运算 NumPy中的ndarray对象重载了许多运算符,使用这些运算符可以完成矩阵间对应元素的运算。matrix对象的优势在于能够实现部分矩阵运算,例如矩阵乘法、逆矩阵等运算。 1) 矩阵乘法 假设a、b表示矩阵,a*b、np.dot(a,b)表示数学中的矩阵乘法运算,np.multiply(a,b)表示矩阵对应元素的乘积。 2) 矩阵转置 矩阵转置的形式为.transpose()|T。 例3.5矩阵转置示例。 程序代码如下: import numpy as np a=np.mat([[4,3,5,-4],[2,1,4,0]]) #定义2×4矩阵a print(a.transpose()) #输出a的转置矩阵 print(a.T) #输出a的转置矩阵 3) 逆矩阵 求矩阵的逆矩阵需要先导入numpy.linalg,用linalg的inv()函数来求逆矩阵,形式如下: linalg.inv()或.I 例3.6求逆矩阵示例。 程序代码如下: import numpy as np a=np.mat([[1,0,0],[3,4,0],[1,2,3]]) #定义3×3矩阵a print(np.linalg.inv(a)) #输出a的逆矩阵 print(a.I) #输出a的逆矩阵 3.1.3生成随机数的常用函数 在NumPy的random模块中含有两类随机数生成函数,一类是浮点型的,常以uniform()为代表; 另一类是整数型的,常以randint()为代表。 1. uniform()函数 使用uniform()函数可以生成给定范围内的浮点型随机数,可以是单个值,也可以是一维数组,还可以是多维数组。其常用语法形式如下: np.random.uniform([,[,]]) 功能: 从一个浮点数均匀分布[low,high]中随机采样,注意定义域是左闭右开,即包含low,不包含high。 参数说明: (1) low为采样下界,float类型,默认值为0。 (2) high为采样上界,float类型,默认值为1。 (3) size为输出样本数目,int或元组(tuple)类型。例如size=(m,n,k),则表示输出m*n*k个样本,该参数省略时输出一个值。 返回值: ndarray类型,其形状和size参数中的描述一致。 例3.7使用uniform()函数生成随机数示例。 程序代码如下: import numpy as np print(np.random.uniform()) #默认为0到1 print(np.random.uniform(1,5))#生成1~5的float数 print(np.random.uniform(1,5,4))#生成一维数组 print(np.random.uniform(1,5,(4,3)))#生成4×3的数组 print(np.random.uniform([1,5],[5,10])) #生成两个元素的一维数组 2. randint()函数 使用randint()函数可以生成给定范围内的整型随机数,可以是单个值,也可以是一维数组,还可以是多维数组。其常用语法形式如下: np.random.randint([,high=None],size=None,dtype='l') 功能: 用于生成一个指定范围内的整数。其中low是下限、high是上限,生成的随机数n有low<=n]区间内的随机数。 (3) size为int类型或元组,指明生成模式。 (4) dtype表示元素的数据类型,可选'int'、'int64',默认为'l'。 例3.8randint()函数应用示例。 程序代码如下: import numpy as np print(np.random.randint(5))#生成0~5的整数 print(np.random.randint(5,size=4))#生成0~5的4个元素的数组 print(np.random.randint(5,10,size=6))#生成5~10的6个元素的数组 print(np.random.randint(5,10,size=(2,3),dtype='int'))#生成5~10的2×3数组 例3.9随机函数生成验证码示例。 程序代码如下: import random #从一个字符串中随机生成若干个字符 def gen_code(n): s='er0dfsdfxcvbn7f989fd' code=' ' for i in range(n): r=random.randint(0,len(s)-1) code+=s[r] return code username=input("输入用户名: ") passwd=input("输入密码:") code=gen_code(5) print("验证码是: ",code) code1=input("输入验证码: ") if code.lower()==code1.lower(): if username=='knn' and passwd=='abc': print("Login success!") else: print("username or password error!") else: print("check code error!") 3.1.4对象转换 在使用字符串、列表、数组和矩阵的过程中经常需要进行相互转换,用户可以使用type()函数查看对象的类型。 1. 列表和字符串相互转换 1) 列表转换为字符串 如果列表中的各元素都是字符串,一般通过join()函数转换成字符串,但是当列表中含有数字类型的元素时,需要先将数字类型的元素转换为字符串。 例3.10列表转换为字符串示例。 程序代码如下: lst1=['This','is','an','apple'] print(' '.join(lst1)) #如果列表中包含数字类型的元素,需要先转换为字符串 lst2=['S1','许文秀','女',20,'计算机系'] print(' '.join([str(x) for x in lst2])) 2) 字符串转换为列表 字符串转换为列表的方法有两种,一是利用列表直接转换,即list(); 二是通过字符串的split()方法转换。 例3.11字符串转换为列表示例。 程序代码如下: str1='Python program' result1=list(str1)#用list()转换 print(result1) result2=str1.split()#默认以空格分隔 print(result2) result3=str1.split(',')#以逗号分隔 print(result3) 2. 数组和字符串相互转换 将数组转换为字符串的方法和将列表转换为字符串的方法是一样的。 例3.12数组转换为字符串示例。 程序代码如下: import numpy as np lst=['This','is','a','program'] arr=np.array(lst) str1=' '.join(arr) print(str1) 将字符串转换为数组可以先将字符串转换为列表,再将列表转换为数组。 例3.13字符串转换为数组示例。 程序代码如下: import numpy as np str1='567232' lst=list(str1) arr1=np.array(lst) print(arr1) 3. 列表和数组相互转换 使用np.array()方法可以将列表转换为数组。 例3.14列表转换为数组示例。 程序代码如下: import numpy as np lst1=[-3,4,8,6] lst2=[[2,3,4],[4,7,1]] arr1=np.array(lst1) arr2=np.array(lst2) print(arr1) print(arr2) 使用tolist()或list()方法可以将数组转换为列表。 例3.15数组转换为列表示例。 程序代码如下: import numpy as np arr1=np.array([-3,4,8,6]) arr2=np.array([[2,3,4],[4,7,1]]) lst1=arr1.tolist() lst2=arr2.tolist() print(lst1) print(lst2) 4. 列表和矩阵相互转换 使用np.mat()方法可以将列表转换为矩阵。 例3.16列表转换为矩阵示例。 程序代码如下: import numpy as np lst=[[1,2,3],[4,5,6]] matr=np.mat(lst) print(type(matr)) print(matr) 将矩阵转换为列表和将数组转换为列表的方法相同。 5. 数组和矩阵相互转换 将数组转换为矩阵和将列表转换为矩阵的方法相同,将矩阵转换为数组和将列表转换为数组的方法相同。 3.1.5数组元素和切片 NumPy多维数组和列表的类型非常类似,同样有访问数组元素和切片的功能,访问数组元素是指获取数组中特定位置元素的过程,切片是指获取数组元素子集的过程。 1. 一维数组元素和切片 一维数组元素和切片与Python列表类似。 例3.17一维数组元素和切片示例。 程序代码如下: import numpy as np arr=np.array([-4,8,12,6,9,11,25]) print(arr[4]) #输出下标为4的元素 print(arr[2:5]) #输出下标为2、3、4的元素 print(arr[1:5:2]) #输出下标为1、3的元素 2. 多维数组元素和切片 多维数组元素的不同维度用逗号隔开,取切片用冒号,多维数组取步长用冒号。 例3.18多维数组元素和切片示例。 程序代码如下: import numpy as np arr=np.arange(12).reshape([3,4]) print(arr[1,2])#输出下标为[1,2]的元素 print(arr[1:,2:])#输出行标为1和2、列标为2和3的元素 print(arr[::2,1])#输出行标为0和2、列标为1的元素 3.2Pandas模块 Pandas是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的。它采用的是矩阵运算,要比Python自带的字典或者列表的效率高得多。 3.2.1Pandas中的数据结构 Pandas有两大数据结构——Series和DataFrame。数据分析的相关操作都围绕着这两种结构进行,它们需要用import pandas as pd语句导入。Series是一种一维数组对象,DataFrame是一个二维的表结构,类似Excel。 1. Series对象 Series对象包含一组数据和一组索引,可以理解为一组带索引的数组。它由两个相关联的数组组合在一起,即主元素数组和index数组。index数组可以是数字或者字符串。创建Series对象的常用形式如下: (1) 通过列表创建,形式为pd.Series([,index=]),其中为数据列表; 为Series的索引,如果没有定义,则默认为(0,1,2,…,n)。 (2) 通过字典创建,形式为pd.Series({:,:,…,:})。 例3.19Series对象创建示例。 程序代码如下: import pandas as pd s1=pd.Series([12,5,7,21],index=[4,2,3,1]) s2=pd.Series([12,5,7,21],index=['a','b','c','d']) s3=pd.Series({'a':21,'b':213,'c':309,'d':210,'e':111}) print(s1) print(s2) print(s3) 2. DataFrame对象 DataFrame是一个表格型的数据结构,包含一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等)。它既有行索引又有列索引,可以被看作由Series组成的字典。 (1) 用二维列表创建DataFrame对象,常用的形式为: pd.DataFrame([,index=][,columns=]) 参数说明: ① 表示二维列表数据。 ② index表示DataFrame的行索引,默认为(0,1,2,…,m)。 ③ columns表示DataFrame的列索引,默认为(0,1,2,…,n)。 例3.20用二维列表创建DataFrame对象示例。 程序代码如下: import pandas as pd datas=[['许文秀','女',20,'计算机系'],['刘世元','男',21,'电信系'],['刘德峰','男',22,'统计系'],['于金凤','女',20,'计算机系']] line_index=['S1','S2','S3','S4'] column_index=['姓名','性别','年龄','系部'] df=pd.DataFrame(datas,index=line_index,columns=column_index) print(df) (2) 用字典方式创建DataFrame对象,形式为: pd.DataFrame([,index=]) 参数说明: ① dict表示字典数据。 ② index表示DataFrame的行索引,默认为(0,1,2,…,m)。 例3.21用字典方式创建DataFrame对象示例。 程序代码如下: import pandas as pd datas ={'姓名':['许文秀','刘世元','刘德峰','于金凤'],'性别':['女','男','男','女'],'年龄':[20,21,22,20],'系部':['计算机系','电信系','统计系','计算机系']} line_index=['S1','S2','S3','S4'] df=pd.DataFrame(datas,index=line_index) print(df) 3.2.2DataFrame的基本属性 DataFrame的基础属性有values、index、columns、ndim和shape等,分别用来获取DataFrame的元素、索引、列名、维度和形状。假设df=pd.DataFrame({'姓名':['许文秀','刘世元'],'性别':['女','男'],'年龄':[20,21],'系部':['计算机系','电信系']},index=['S1','S2']),DataFrame的基本属性如表3.2所示。 表3.2DataFrame的基本属性 属性和方法说明示例结果 values 获取ndarray类型的元素 df.values [['许文秀' '女' 20 '计算机系'] ['刘世元' '男' 21 '电信系']] index获取行索引df.indexindex(['S1','S2'],dtype='object') 续表 属性和方法说明示例结果 axes 获取行索引及列索引 df.axes [index(['S1' 'S2'],dtype='object'),index(['姓名','性别','年龄','系部'],dtype='object')] columns 获取列名列表 df.columns index(['姓名','性别','年龄','系部'],dtype='object') size获取元素个数df.size8 ndim获取维度df.ndim2 shape获取形状df.shape(2,4) 3.2.3DataFrame的常用方法 继续利用3.2.2节中的例子,DataFrame的常用方法如表3.3所示。 表3.3DataFrame的常用方法 属性和方法说明示例结果 iloc[<行序>,<列序>]按序号获得元素df.iloc[:,0:2] 姓名性别 S1许文秀女 S2刘世元男 loc[<行索引>,<列索引>]按索引获得元素df.loc['S2','姓名']刘世元 df.head(i)显示前i行数据df.head(1) 姓名性别年龄系部 S1许文秀女20计算机系 df.tail(i)显示后i行数据df.tail(1) 姓名性别年龄系部 S2刘世元男21电信系 df.describe()查看数据列的统计信息df.describe()年龄列的count、mean、std、min、max、25%(下四分位数)、50%(中位数)、75%(上四分位数)的值 del删除指定列del df['性别']删除性别列 drop(columns=[<列名1>,<列名2>,…,<列名n>])同时删除多个列df.drop(columns=['性别','系部']) 姓名年龄 S1许文秀20 S2刘世元21 rename(columns={<原名1>:<新名1>,<原名2>:<新名2>,…,<原名n>:<新名n>})同时修改多个列名df.rename(columns={'姓名':'Name','性别':'Sex','年龄':'Age','系部':'Dept'}) Name SexAgeDept S1许文秀女20计算机系 S2刘世元男21电信系 df.copy()复制dfdf1=df.copy()df1中为df内容 3.2.4DataFrame的数据查询与编辑 1. 数据查询 数据查询一般都是通过索引来操作的。 1) 查询列数据 通过列索引标签或者属性的方式可以单独获取DataFrame的列数据,返回的数据类型为Series。注意在选取列时不能使用切片的方式,若超过一个列名,用df[[,< column_name_2>,…,]]形式。 例3.22查询列数据示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas,index=['S1','S2','S3','S4']) print('查询姓名列: \n',df[['姓名']]) print('查询姓名和年龄列\n: ',df[['姓名','年龄']]) 2) 查询行数据 通过行索引或者行索引位置的切片形式获取行数据(从0开始,左闭右开)。DataFrame提供的head()和tail()方法分别用于获取开始和末尾的连续多行数据。 例3.23查询行数据示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas,index=['S1','S2','S3','S4']) print('查询前两行: \n',df[:2]) print('查询第2行: \n',df[1:2]) print('查询前3行: \n',df.head(3)) print('查询后两行: \n',df.tail(2)) 3) 同时查询行和列 切片查询行的限制比较大,查询单独的几行数据可以采用Pandas提供的iloc[]和loc[]方法实现。 例3.24同时选择行和列示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas,index=['S1','S2','S3','S4']) print('查询序号为S1和S3的同学的姓名和系部: \n',df.loc[['S1','S3'],['姓名','系部']]) print('查询第1行和第3行的第2列: \n',df.iloc[[1,3],[1]]) 4) 条件查询 条件查询由逻辑表达式构成查询条件,获取符合条件的记录。 例3.25条件查询示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas,index=['S1','S2','S3','S4']) print('查询姓名为刘德峰的行数据\n',df[df['姓名']=='刘德峰']) print('查询计算机系的女同学: \n',df[(df['性别']=='女') & (df['系部']=='计算机系')]) 2. 数据编辑 DataFrame对象的数据编辑方法有很多,这里只介绍常用的几种。 1) 添加数据 添加一行数据可以通过append()方法实现,创建一个新的数据列的方法类似于在字典中添加项的方法。 例3.26 添加新的行或列示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas) data_1={'姓名':'王文庆','性别':'男','年龄':21,'系部':'电信系'} df1=df.append(data_1,ignore_index=True) #添加一行数据 print('添加新的数据行: \n',df1) df1['籍贯']=['河北省','天津市','河北省','重庆市','江苏省']#添加一列数据 print('添加新的数据列: \n',df1) 2) 删除数据 删除数据直接用drop()方法,行、列数据通过axis参数设置,其中0默认为删除行,1默认为删除列。默认删除数据不修改原数据,inplace=True表示在原数据上删除。 例3.27删除行或列示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas) df1=df.drop([2],axis=0,inplace=False) #删除序号为2的行,即第3行 print('删除第3行: \n',df1) df.drop('系部',axis=1,inplace=True) #删除系部列 print('删除系部列: \n',df) 3) 修改数据 修改行、列标题使用df.rename()方法,修改数据只需要对选择的数据进行赋值。 例3.28修改行、列标题示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas) print('原数据: \n',df) df1=df.rename({0:'S1',1:'S2',2:'S3',3:'S4'}) #修改行标题 print('修改行标题: \n',df1) df1.rename(columns={'姓名':'name','性别':'sex','年龄':'age','系部':'dept'},inplace=True) print('修改列标题: \n',df1) 例3.29数据修改示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas) df.loc[2,'姓名']='刘得锋'#将姓名刘德峰改成刘得锋,或用df.iloc[2,0] print('修改一个元素的值: \n',df) df.loc[1,['姓名','性别']]=['陈晓晴','女'] #修改第2行的姓名和性别 print('修改某行几个元素的值: \n',df) df.iloc[:,2]=[21,22,23,21]#修改第3列的内容 print('修改某列的值: \n',df) 3.2.5Pandas数据的四则运算 两个DataFrame对象可以进行四则运算,运算法则是对应元素进行运算,对于不同维度的对象,无对应元素结果取NaN值,也可以利用fill_value=先填充,后计算。 例3.30两个DataFrame对象的四则运算示例。 程序代码如下: import numpy as np import pandas as pd df1=pd.DataFrame(np.arange(12).reshape((3,4)),columns=list('abcd')) df2=pd.DataFrame(np.arange(20).reshape((4,5)),columns=list('abcde')) print('A=\n',df1,'\nB=\n',df2) #打印DataFrame对象 print('A+B=\n',df1.add(df2,fill_value=0)) #(或用df1+df2)输出df1与df2的和 print('A-B=\n',df1.sub(df2,fill_value=0)) #(或用df1-df2)输出df1与df2的差 print('A*B=\n',df1.mul(df2,fill_value=0)) #(或用df1*df2)输出df1与df2的积 print('A/B=\n',df1.div(df2,fill_value=0)) #(或用df1/df2)输出df1与df2的商 3.2.6函数变换 在数据清洗工作中经常需要对数据进行各种函数变换,为此Pandas提供了map()、apply()和applymap()等函数。 1. map()函数 map()函数主要用在Series对象中,用来对Series对象中的元素进行变换。 例3.31map()函数变换示例。 程序代码如下: import pandas as pd datas={'姓名':['许文秀','刘世元','刘德峰','于金凤'], '性别':['女','男','男','女'], '年龄':[20,21,22,20], '系部':['计算机系','电信系','统计系','计算机系']} df=pd.DataFrame(datas) def sex_map(x): #将性别'男'改为'M'、'女'改为'F' sex='F' if x=='男': sex ='M' return sex #该函数也可以用字典sex_map={'男':'M','女':'F'}替代 df['性别']=df['性别'].map(sex_map) print(df) 2. apply()函数 apply()是Pandas模块的一个很重要的函数,可以直接用于DataFrame和Series对象,它经常结合NumPy库和隐函数lambda来使用。 例3.32apply()函数应用示例。 程序代码如下: import pandas as pd import numpy as np df=pd.DataFrame(np.arange(12).reshape((3,4)),columns=list('ABCD')) print('df中原始数据为: \n',df) print('计算每个元素的平方根: \n',df.apply(np.sqrt)) print('计算每一列元素的平均值:\n',df.apply(np.mean)) print('计算每一行元素的平均值:\n',df.apply(np.mean,axis = 1)) print('增加第E列,为前面4列元素之和: ') def Add_a(x): return x.A+x.B+x.C+x.D df['E']=df.apply(Add_a,axis=1) print(df) print('列E中的所有元素加5: ') df.E=df.E.apply(lambda x:x+5) print(df) print('第E列元素被3整除的均赋值Yes,否则赋值No: ') df.E=df.E.apply(lambda x: 'Yes' if x%3==0 else'No') print(df) 3. applymap()函数 applymap()函数是元素级别的操作,返回结果是对DataFrame中的每个元素执行指定的函数操作。 例3.33applymap()函数应用示例。 程序代码如下: import pandas as pd df=pd.DataFrame([[1,2.12,3.245],[3.356,4.56,2.1101]],columns=list('abc'),index=[2,3]) def f(x): return len(str(x)) #对每一个元素求长度,其中1按1.0计算 print(df.applymap(f)) 4. map()、apply()和applymap()在应用上的区别 简单总结起来,这3个函数在应用上有以下几点区别: (1) map()函数只能作用于Series对象中的每个元素。 (2) apply()函数既可以作用于Series对象中的每个元素,也可以作用于DataFrame对象中的行或列。 (3) applymap()只能作用于DataFrame对象中的每个元素。 3.2.7排序 在数据分析过程中,有时需要根据索引的大小或者值的大小对Series对象和DataFrame对象进行排序,使用sort_index()函数可以根据行或列的索引进行排序,使用sort_values()函数可以根据行或列的值进行排序。 例3.34Series对象按索引进行排序示例。 程序代码如下: import pandas as pd s=pd.Series([1,2,3],index=['a','c','b']) print('按Series对象的索引进行升序排序: \n',s.sort_index()) #默认是升序排序 print('按Series对象的索引进行降序排序: \n',s.sort_index(ascending=False)) 例3.35Series对象按值进行排序示例。 程序代码如下: import pandas as pd import numpy as np s=pd.Series([np.nan,1,7,2,3],index=['a','c','e','b','d']) print('按Series对象的值进行升序排序: \n',s.sort_values()) #默认是升序排序 print('按Series对象的值进行降序排序: \n',s.sort_values(ascending=False)) 说明: 在对值进行排序的时候,无论是升序还是降序,缺失值(NaN)都会排在最后。 例3.36DataFrame对象按索引排序示例。 程序代码如下: import numpy as np import pandas as pd a=np.arange(9).reshape(3,3) data=pd.DataFrame(a,index=['0','2','1'],columns=['c','a','b']) print('按行的索引进行升序排序:\n',data.sort_index())#默认按行升序排序 print('按行的索引进行降序排序:\n',data.sort_index(ascending= False)) print('按列的索引进行升序排序:\n',data.sort_index(axis=1))#默认按列升序排序 print('按列的索引进行降序排序: \n',data.sort_index(axis=1, ascending=False)) 例3.37DataFrame对象按值排序示例。 程序代码如下: import pandas as pd import numpy as np data=[[9,3,1],[1,2,8],[1,0,5]] df=pd.DataFrame(data,index=['S1','S2','S3'],columns=['c','a', 'b']) print('按指定列的值大小顺序进行排序: \n',df.sort_values(by='c')) #默认升序 print('按指定多列的值大小顺序进行排序: \n',df.sort_values(by= ['c','a'])) #在对DataFrame对象的值进行排序时,要使用by指定某一行(列)或者某几行(列) print('按指定行值进行排序: \n',df.sort_values(by='S1',axis=1)) #在指定行值进行排序的时候必须设置axis=1 3.2.8汇总与统计 Pandas对象拥有一组常用的数学和统计方法,和NumPy数组相比,它们只对真实值(非缺失数据)进行统计。 1. 常用方法 假设df=pd.DataFrame([[np.nan,1,3],[4,5,6]],index={'S1','S2'},columns= ['c','a','b']),Pandas对象的常用方法及示例如表3.4所示。 2. 协方差和相关系数 协方差(Covariance)反映两个样本/变量X、Y之间的相互关系以及相关程度。如果协方差为正,说明X、Y同向变化,协方差越大,说明同向程度越高; 如果协方差为负,说明X、Y反向变化,协方差越小,说明反向程度越高。 表3.4Pandas对象的常用方法及示例 方法说明示例结果 count按列统计非NaN值的数量df.count()输出列名及各列非NaN值的数量 describe 针对Series或各DataFrame列计算汇总统计df.describe() 输出各列的count、mean、std、min、max等值 max、min最大值和最小值df.max()输出列名及各列的最大值 sum值的总和df.sum()输出列名及各列的和 mean值的平均数df.mean()输出列名及各列的平均值 median值的算术中位数(二分位数)df.median()输出列名及各列的中位数 var样本值的方差df.var()输出列名及各列的方差 std样本值的标准差df.std()输出列名及各列的标准差 diff一阶差分df.diff()输出列名及各列的一阶差分 相关系数(Correlationcoefficient)反映两个样本/变量之间的相关程度。相关系数也可以看成是两个变量的量化影响、标准化后的特殊协方差。相关系数在-1~+1变化: (1) 当相关系数为1的时候两者相似度最大,同向正相关。 (2) 当相关系数为0的时候两者没有相似度,两个变量无关。 (3) 当相关系数为-1的时候两者变化的反向相似度最大,完全反向负相关。 使用cov()方法和corr()方法分别计算两个Series对象或DataFrame对象的协方差和相关系数。 例3.38协方差和相关系数示例。 程序代码如下: import pandas as pd df = pd.DataFrame({ "年龄":[8,9,10,11,12], "身高":[130,135,140,141,150]}) print('\n年龄和身高的协方差为: ',df['年龄'].cov(df['身高'])) print('\n年龄和身高的相关系数为: ',df['年龄'].corr(df['身高'])) 3.2.9数据的分组与统计 Pandas提供了较好的分组与统计功能,可以很方便地对数据进行不同维度的分组与统计操作。 1. 分组 分组(Groupby)就是对数据集进行分组,然后对每组数据进行统计分析。Pandas使用groupby()进行分组,它没有进行实际运算,只是包含分组的中间数据。 按列名分组的常用形式为.groupby()。 例3.39groupby()分组运算示例。 程序代码如下: import pandas as pd import numpy as np dict={'key1' : ['a', 'b', 'a', 'b','a', 'b', 'a', 'a'], 'key2' : ['one', 'one', 'two', 'three','two', 'two', 'one', 'three'], 'data1': np.random.randn(8), 'data2': np.random.randn(8)} df=pd.DataFrame(dict) print('\n创建的DataFrame对象: \n',df) grouped1=df.groupby('key1') print('\n第一分组均值: \n',grouped1.mean())#DataFrame根据key1进行分组 grouped2=df['data1'].groupby(df['key1'])#DataFrame的data1列根据key1进行分组 print('\n第二分组均值: \n',grouped2.mean()) print('\n分组一元素个数: \n',grouped1.size()) print('\n分组二元素个数: \n',grouped2.size()) 用户可以将分组关键字定义为列表或多层列表,也可以选定多个关键字分组。 例3.40自定义key分组及多层分组示例。 程序代码如下: import pandas as pd import numpy as np dict={'key1' : ['a', 'b', 'a', 'b','a', 'b', 'a', 'a'], 'key2' : ['one', 'one', 'two', 'three','two', 'two', 'one', 'three'], 'data1': np.random.randn(8),'data2': np.random.randn(8)} df=pd.DataFrame(dict) print(df) self_def_key=[0, 1, 2, 3, 3, 4, 5, 7] print(df.groupby(self_def_key).size())#按自定义关键字分组,列表 print(df.groupby([df['key1'], df['key2']]).size())#按自定义关键字分组,多层列表 grouped2=df.groupby(['key1', 'key2']) #按多个列进行多层分组 print(grouped2.size()) grouped3=df.groupby(['key2', 'key1']) #多层分组按关键字顺序进行 print(grouped3.mean()) #unstack()可以将多层索引结果转换成单层的DataFrame print(grouped3.mean().unstack()) 2. 统计 Pandas提供了基于行和列的统计操作,统计运算方法有sum()、mean()、max()、min()、size()、describe()等。 例3.41分组后应用统计函数示例。 程序代码如下: import pandas as pd import numpy as np dict={'key1' : ['a', 'b', 'a', 'b','a', 'b', 'a', 'a'], 'key2' : ['one', 'one', 'two', 'three','two','two', 'one', 'three'], 'data1': np.random.randn(8),'data2': np.random.randn(8)} df=pd.DataFrame(dict) print(df) #使用统计函数 print(df.groupby('key1').sum()) print(df.groupby('key1').max()) print(df.groupby('key1').min()) print(df.groupby('key1').mean()) print(df.groupby('key1').size()) print(df.groupby('key1').count()) print(df.groupby('key1').describe()) 3.2.10Pandas数据的读取与存储 数据大部分存储在文件中,因此Pandas支持复杂的I/O操作,它的API支持众多的文件格式,例如CSV、TXT、Excel、MySQL等。 1. CSV文件 CSV(Comma Separated Values)文件是最通用的一种文件格式,它可以被非常容易地导入各种计算机表格及数据库中。此文件一行即为数据表的一行,生成的数据表字段用半角逗号隔开。Pandas利用writerow()方法写入CSV文件数据,利用read_csv()方法读取CSV文件数据。 例3.42在指定路径下创建CSV文件示例。 程序代码如下: import csv import os os.chdir('D:\\Data_Mining') #改变当前路径 head=['学号','姓名','性别','年龄','系部'] #定义文件头 lst=[['S1','许文秀','女',20,'计算机系'], ['S2','刘世元','男',21,'电信系'], ['S3','刘德峰','男',22,'统计系'], ['S4','于金凤','女',20,'计算机系']] with open ('test.csv', 'a', newline=' ') as f: #以追加方式打开或创建 f_csv=csv.writer(f) f_csv.writerow(head) #写入文件头 for i in range(4): #按行写入文件 f_csv.writerow(lst[i]) 例3.43Pandas读取CSV文件示例。 程序代码如下: import pandas as pd import os os.chdir('D:\\Data_Mining') #设置当前路径 data=pd.read_csv('test.csv',encoding = 'gb18030') #读取文件数据 print(data) 2. Excel文件 Pandas依赖xlrd模块处理Excel文件,因此需要提前安装该模块,其安装命令为pip install xlrd。注意xlrd 1.2.0之后的版本不支持XLSX格式,仅支持XLS格式。 Pandas利用read_excel()方法读取Excel文件数据后返回DataFrame对象。 例3.44Pandas读取Excel数据文件示例。 程序代码如下: import pandas as pd file='D:\\Data_Mining\stud.xls' df=pd.read_excel(file) print('获得Excel文件数据:\n',df) 如果是将整个DataFrame写入Excel,则调用to_excel()方法即可实现。 例3.45Pandas将DataFrame对象数据写入Excel文件示例。 程序代码如下: import pandas as pd head=['学号','姓名','性别','年龄','系部'] data=[['S1','许文秀','女',20,'计算机系'], ['S2','刘世元','男',21,'电信系'], ['S3','刘德峰','男',22,'统计系'], ['S4','于金凤','女',20,'计算机系']] df=pd.DataFrame(data,columns=head) file='D:\\Data_Mining\stud11.xlsx' df.to_excel(file) 3. 读取MySQL数据 Pandas利用read_sql()方法读取MySQL文件。 例3.46读取MySQL数据示例。 程序代码如下: import pymysql con =pymysql.connect(host='localhost',user='root', password='root', database='test',port=3306,charset='utf-8') sql_select ='select * from a'df = pd.read_sql(sql_select, con) 其中,host是主机名,一般填写IP地址,user代表数据库用户名,password代表数据库密码,database代表需要连接的数据库名称,port代表端口,charset代表编码格式,一般使用utf8。 3.3Matplotlib图表绘制基础 Matplotlib是一个Python工具箱,用于科学计算的数据可视化,它是一个非常好用的库,无论是写论文需要画图,还是在数据调研中显示数据相关性,都是一个很好的选择。 3.3.1Matplotlib简介 Matplotlib是Python中基于NumPy的一套绘图工具包。Matplotlib提供了一整套在Python下实现类似MATLAB的纯Python第三方库,其风格与MATLAB相似,并且继承了Python简单明了的优点。近年来,在开源社区的推动下,Matplotlib在科学计算领域得到了广泛应用,成为Python中应用非常广的绘图工具包之一。 3.3.2Matplotlib绘图基础 Matplotlib绘图流程如图3.1所示。 图3.1Matplotlib绘图流程 使用Matplotlib模块进行绘图主要有3个步骤,第一步创建画布与子图; 第二步准备数据,进行绘图及修饰; 第三步保存与显示图形。 1. 创建画布与子图 该部分的主要作用是创建一张空白画布,并可以选择是否将整个画布划分为多个部分,方便在同一幅图上绘制多个图形。最简单的绘图可以省略第一部分,然后直接在默认的画布上进行图形绘制。创建画布与子图涉及的函数如表3.5所示。 表3.5创建画布与子图涉及的函数 函数名功能 figure()创建一个空白画布,可以指定画布的大小、像素 figure.add_subplot()创建并选中子图,可以指定子图的行数、列数 subplots_adjust()调整子图之间的间距,wspace为调整宽度,hspace为调整高度 创建子图的常用步骤如下: (1) 利用plt.figure()函数创建画布(只绘制一幅图时,取默认画布,所以可以省略这一步)。 (2) 利用plt.subplot()函数创建子图,需要传入行、列、索引等参数。 (3) 利用axi=plt.subplot(m,n,i)(i=1,2,…,m×n)在画布中创建m×n个图形。 (4) 给子图axi绘制图形。 (5) 利用plt.show()展示图片,释放内存。 例3.47创建多个子图示例。 程序代码如下: import numpy as np import matplotlib.pyplot as plt x1=np.arange(-2,2,0.01) p1=plt.figure(figsize=(8,4),dpi=80) #确定画布大小 ax1=p1.add_subplot(1,2,1) #创建一个1行2列的子图,并开始绘制第一幅 plt.title('Power Function') plt.plot(x1,x1**2) plt.plot(x1,x1**4) plt.legend(['y=x^2','y=x^4']) ax2=p1.add_subplot(1,2,2) plt.title('e^x/log(x)') x2=np.arange(1,4,0.01) plt.plot(x2,np.exp(x2)) plt.plot(x2,np.log(x2)) plt.legend(['y=e^x','y=log(x)']) plt.show()#显示绘制出的图 程序运行结果如图3.2所示。 图3.2例3.47的运行结果 2. 绘图及修饰 该部分是绘图的主体部分,其中添加标题、坐标轴名称,绘制图形等步骤是并列的,没有先后顺序,可以先绘制图形,也可以先添加各类标签,但是添加图例一定要在绘制图形之后。绘图及修饰涉及的函数如表3.6所示。 表3.6绘图及修饰涉及的函数 函数名功能 plt.title()在当前图形中添加标题,可以指定标题的名称、位置、颜色、字体大小等参数 plt.xlabel()在当前图形中添加X轴名称,可以指定位置、颜色、字体大小等参数 plt.ylabel()在当前图形中添加Y轴名称,可以指定位置、颜色、字体大小等参数 plt.xlim()指定当前图形的X轴的范围,只能确定一个数值区间,而无法使用字符串标识 plt.ylim()指定当前图形的Y轴的范围,只能确定一个数值区间,而无法使用字符串标识 plt.xticks()指定X轴刻度的数目与取值 plt.yticks()指定Y轴刻度的数目与取值 plt.legend()指定当前图形的图例,可以指定图例的大小、位置、标签 3. 保存与显示图形 该部分用于保存与显示图形,主要涉及的函数如表3.7所示。 表3.7保存与显示图形涉及的函数 函数名功能 plt.savafig()保存绘制的图形,可以指定图片的分辨率、边缘的颜色等参数 plt.show()在本机显示图形 例3.48某市某周每天的最高气温如表3.8所示。 表3.8某市某周每天的最高气温 日期周一周二周三周四周五周六周日 最高气温/℃15202223201816 图3.3例3.48的运行结果 绘制该周的温度变化曲线。 程序代码如下: import numpy as np import matplotlib.pyplot as plt x=np.arange(1,8)#绘图及修饰 y=np.array([15,20,22,23,20,18,16]) plt.plot(x,y) plt.show()#显示图形 程序运行结果如图3.3所示。 3.3.3使用Matplotlib简单绘图 Matplotlib是Python中的一个简单又完善的开源绘图库,用户只需要编写几行代码就可以生成绘图。Matplotlib含有pyplot和pylab两个绘图模块,其中pyplot提供了一套和MATLAB类似的绘图API,将众多绘图对象所构成的复杂结构隐藏在这套API内; pylab包含了许多NumPy和pyplot模块中常用的函数,方便用户快速进行计算和绘图,非常适合在Python交互式环境中使用。 1. pyplot模块 Matplotlib.pyplot是一个有命令风格的函数集合,各种状态通过函数调用保存起来,以便随时跟踪当前图像和绘图区域等对象。利用绘图函数可以绘制折线图、散点图、柱状图、饼图、直方图等图像。引入pyplot模块的常用语句为import matplotlib.pyplot as plt。 1) plot()函数 使用Matplotlib 提供的plot()函数绘制二维图像,展现变量的变化趋势。plot()函数的常用形式如下: plt.plot(,,