本文转载自微信公众号《数据仓库宝库》,作者王凯等,转载请联系数据仓库宝宝库公众号.01处理缺失数据缺失数据是数据文件中最常见的问题之一。Pandas中的缺失值表示为NA,其中numeric类型的缺失值标记为NaN(NotaNumber),datetime类型的缺失值标记为NaT(NotaTime)。缺失值的存在可能会导致后续数据分析出现错误。在清洗数据之前,首先判断数据中是否存在缺失值,以及缺失值的准确位置。Pandas提供了isna()和notna()方法,用于快速确定Series和DataFrame对象中缺失值的位置。语法如下:pd.isna(data)ordata.isna()pd.notna(data)ordata.notna()data可以是一个Series对象,返回值是一个BooleanSeries对象;也可以是DataFrame对象,返回值为布尔型DataFrame对象;也可以是标量值,此时返回一个布尔值。对于isna方法,如果data中包含NA值,则返回值对应的位置为True,其余普通元素对应的位置为False。notna方法与isna方法相反。如果data中包含NA值,则返回值对应位置为False,其他普通元素对应位置为True。Pandas提供了几种处理缺失值的方法,即重新分配缺失值、删除缺失值所在的行、删除数据缺失率高的列等。删除缺失值的方法一般用在缺失值较少的情况下缺失值,对整体数据影响不大。1)pandas提供了fillna方法,可以将缺失值重新赋值给新的元素值。常用的语法格式如下:result=data.fillna(value,method=None,…)其中data可以是Series对象,也可以是DataFrame对象。value可以是一个固定的元素,比如0;value也可以是字典对象、Series对象或DataFrame对象,用于替换数据中匹配标签(Series对象)或匹配列标签(DataFrame对象)对应的缺失值是不同的值,数据中缺失值不匹配的值将不会被替换。method表示填充NA值的方法,默认为None。当method='ffill'或'method=pad'时,使用最后一个有效值填充NA值,当method='bfill'或'method=backfill'时,使用下一个有效值填充NA值。fillna的返回值是新分配的Series或DataFrame对象。2)pandas提供了dropna方法实现按行或列删除NA值的功能。语法格式如下:result=data.dropna(axis=0,how='any',...)如果data是Series对象,那么axis只能等于0,直接删除所有NA值。如果data是DataFrame对象,参数axis为0或'index'表示删除缺失值所在的行;如果axis设置为1或'columns',则删除缺失值所在的列;axis默认值为0,how='any'表示只要有NA值,就删除该行或列;how='all'表示只有当所有元素都是NA值时才会执行删除操作;如何默认为“任何”。dropna的返回值是一个去掉了缺失值的Series或DataFrame对象。3)Pandas还为Series和DataFrame提供了interpolate()方法,通过插值来补充缺失的数据点。语法格式如下:result=data.interpolate(method='linear',axis=0,…)method表示使用插值方法,默认为'linear'进行线性插值。还常用的是“时间”,它根据时间间隔进行插值。此外,method还提供了更高级的插值方法,如Scipy库中的'nearest','zero','slinear','quadratic','cubic','spline','barycentric','polynomial'等.axis参数的使用方式与dropna方法相同。以下代码清单演示了Pandas提供的缺失数据方法的用法。代码清单 Pandas缺失数据方法使用示例1importpandasaspd2importnumpyasnp3df=pd.DataFrame({'A':[1,2.1,np.nan,4.7,5.6],'B':[.25,np.nan,np.nan,4,12.2]})4print('df:\n',df)5print('df中的元素是否为缺失值:\n',pd.isna(df))6df1=df.fillna(0)#用固定值填充7print('用0填充缺失值:\n',df1)8df2=df.fillna(value={'A':1,'B':2})#WillNaNincolumnsA和B换成1和29print('用字典填充缺失值后的数据:\n',df2)10df3=df.fillna(df.mean())#用每一列的平均值来fill11print('用每列的平均值填充缺失值后的数据:\n',df3)12df4=df.dropna()13print('删除缺失值后的数据:\n',df4)14df5=df。interpolate()15print('缺失值后的数据用线性插值法填充:\n',df5)16df6=df.interpolate(method='多项式',order=2)17print('缺失值后的数据value用多项式插值法填充:\n',df6)程序执行后输出结果如下:df:AB01.00.2512.1NaN2NaNNaN34.74.0045.612.20df中的元素是否缺失值:AB0FalseFalse1FalseTrue2TrueTrue3FalseFalse4FalseFalse数据用0填充缺失值后:AB01.00.2512。10.0020.00.0034.74.0045.612.20字典后数据填充数据:AB01.00.2512.12.0021.02.0034.0045.612.20各列平均值后填充数据。6012.200000删除缺失值后的数据:AB01.00.2534.74.0045.612.20线性插值填充缺失值后的数据:AB01.00。2512.11.5023.42.7534.74.0045.612.20多项式插值法填充缺失值后的数据:AB01.0000000.25012.100000-1.97523.433333-0.72534.7000004.00045.60000012code.203下面代码list3中的简单解释dictionary创建了一个5行2列的DataFrame对象df,使用Numpy库中的np.nan设置了几个缺失值,如第4行print函数的输出所示。第五行代码使用了isna确认df中哪些元素缺失值的方法。返回结果中True表示df中对应位置为缺失值,False表示对应位置为正常值。第六行代码使用fillna方法将df中的缺失值填充为固定值0,并将返回结果赋值给新的DataFrame对象df1,如第7行print函数的输出所示。第8行使用fillna方法使用字典{'A':1,'B':2}填充df中的缺失值,A列的NaN用1填充,B列的NaN用1填充2、并将返回的结果赋值给新的DataFrame对象df2,如第9行print函数的输出所示。第10行使用fillna方法使用df.mean()填充df中的缺失值。df.mean()的返回值是一个Series对象类型,表示df每一列的平均值。然后fillna方法用平均值依次填充df每一列的缺失值,并将返回结果赋值给新的DataFrame对象df3,如第11行print函数的输出所示.第12行代码通过dropna方法删除df中的缺失值,采用默认参数设置,即删除所有至少包含一个缺失值的行,并将返回结果赋值给新的DataFrame对象df4,如第13行print函数的输出所示。第14行代码使用interpolate方法对df中的缺失值进行插值,采用默认参数设置,即以列为单位进行线性插值,并将返回结果赋值给新的DataFrame对象df5,如第15行的print函数显示了输出结果。第16行代码使用interpolate方法对df中的缺失值进行插值。参数method='polynomial'表示使用多项式插值法,order=2指定多项式的阶数为2,将返回的结果赋值给一个新的DataFrame对象df6,如输出所示第17行的print函数。Tips上面介绍的fillna、dropna、interpolate等处理缺失值的方法,都是在数据的副本上进行处理,不会改变原始数据。02删除重复数据除了缺失数据外,数据文件中也可能存在重复数据,影响分析结果。因此,在数据清洗阶段也需要删除重复数据。判断数据中是否存在重复行,可以使用Pandas提供的duplicated方法。常用的语法格式如下:data.duplicated(subset=None,keep='first',…)data可以是一个Series对象,也可以是一个DataFrame对象,返回值是一个代表重复行的布尔型Series对象。当数据是Series对象时,复制方法中没有子集参数。subset是一个列标签参数,表示考虑一些特定的列来识别重复数据,默认是考虑所有的列。keep决定标记哪些重复数据,默认为'first',即data中每组重复数据,第一次出现的标记为False,其他重复的位置标记为True。当keep='last'时,表示最后出现的重复数据标记为False,其余位置为True。您可以使用drop_duplicates方法删除重复行。常用语法格式如下:result=data.drop_duplicates(subset=None,keep='first',…)drop_duplicates方法的参数含义与duplicated方法相同。keep参数决定保留哪一行重复数据。返回值是一个包含去重数据的Series或DataFrame对象。Pandas还可以使用drop_duplicates方法来处理数据标签中存在的重复项。具体方法是:先使用Index.duplicated方法判断数据标签中是否存在重复值,然后使用得到的布尔数组对数据进行行切片。下面的代码清单演示了使用Pandas提供的处理重复数据的方法。代码清单 Pandas如何处理重复数据的例子1importpandasasspd2df=pd.DataFrame({'brand':['YumYum','YumYum','Indomie','Indomie','Indomie'],'style':['杯子','杯子','杯子','pack','pack'],'rating':[4,4,3.5,15,5]},index=['a','a','b','c','d'])3print('df:\n',df)4print('对于所有的列,df:\n的行中是否有重复项',df.duplicated())5df1=df.drop_duplicates()6print('去除以上重复后的df:\n',df1)7print('对于brand和style列,df的行是否有重复:\n',df.duplicated(subset=['brand','style']))8df2=df.drop_duplicates(subset=['brand','style'])9print('dfafterremovedtheaboveduplicates:\n',df2)10print('df的索引是否有重复:\n',df.index.duplicated(keep='last'))11df3=df[~df.index.duplicated(keep='last')]12print('删除索引duplicationdfaftertheitem:\n',df3)程序执行后输出结果如下:df:brandstyleratingaYumYumcup4.0aYumYumcup4.0bIndomiecup3.5cIndomiepack15.0dIndomiepack5.0对于所有列,df的行是否有重复:aFalseaTruebFalsecFalsedFalsedtype:bool删除上面重复后的df:brandstyleratingaYumYumcup4.0bIndomiecup3.5cIndomiepack15.0dIndomiepack5.0对于brand和style的列,行是否有重复ofdf:aFalseaTruebFalsecFalsedTruedType:booldf删除上述重复项后:brandstyleeratingaYumYumcup4.0bIndomiecup3.5cIndomiepack15.0df的索引是否有重复项:[TrueFalseFalseFalseFalse]df删除索引重复项后:brandstyleratingaYumYumcup4.0bIndomiecup3.5cIndomiepack15.0dIndomiepack5.0下面通过第二行对代码列表中的代码进行简单说明ofcode字典创建了一个5行3列的DataFrame对象df,并将index参数设置为['a','a','b','c','d'],如输出所示打印函数在第3行显示。第四行代码使用duplicated方法确认df中是否有重复数据,使用默认参数设置,即根据df的所有列来识别重复数据。对于df中的每一组重复数据,第一次出现的标记为False,其他重复的位置标记为True,返回值是一个Series对象。从print函数的输出分析,df中第二行有重复数据。第五行代码通过drop_duplicates方法删除第四行代码确定的重复数据所在行,并将返回结果赋值给新的DataFrame对象df1,如第6行print函数的输出所示第七行代码使用了duplicated方法来确认df中是否有重复数据。subset=['brand','style']表示根据df的brand和style两列来识别重复数据。对于df中的每一组重复数据,第一次出现的标记为False,其他重复的位置标记为True,返回值是一个Series对象。从print函数的输出分析,df中的第二行和第五行是重复的数据。第8行通过drop_duplicates方法删除第6行确定的重复数据所在行,并将返回结果赋值给新的DataFrame对象df2,如第9行print函数的输出所示。第10行代码使用duplicated方法确认df.index(即df的行标签)是否存在重复。keep='last'表示对于df.index中的每一组重复数据,最后出现的位置标记为Fasle,其他重复的位置标记为True,返回值为一维布尔数组。从print函数的输出分析,df中第1行的行标签是重复的。第11行代码通过布尔数组切片的方式删除df中行标签重复的行。首先对第10行代码得到的布尔数组进行反转,即把第一行重复项标记为Fasle,其他项标记为True;然后用得到的新布尔数组对df进行切片,截取True对应的行。并将返回的结果赋值给新的DataFrame对象df3,如第12行print函数的输出所示。Tips1)上面介绍的drop_duplicates方法也是在数据的副本上删除,不改变原始数据。2)Pandas还提供了del、drop等方法,通过positionindex或labelindex删除数据中指定的行或列。本文节选自《Python数据分析与应用》,经出版社授权发布。
