当前位置:首页 > IT科技类资讯

两大步骤,29行代码学会数据清洗

本文转载自微信公众号「数仓宝贝库」,两大步骤作者王恺 等。行代洗转载本文请联系数仓宝贝库公众号。码学

 01处理缺失数据

缺失数据是据清数据文件中最常见的问题之一。在Pandas中的两大步骤缺失值表示为NA,其中数值类型的行代洗缺失值标记为NaN(Not a Number),datetime类型的码学缺失值标记为NaT(Not a Time)。缺失值的据清存在可能会引起后续的数据分析错误。

在清洗数据之前,两大步骤首先要确定数据中是行代洗否存在缺失值以及缺失值的确切位置。Pandas提供了isna()和notna()方法,码学用于快速确定Series和DataFrame对象中缺失值的据清位置,其语法格式如下:

pd.isna(data) 或者 data.isna() pd.notna(data) 或者 data.notna()

data可以是两大步骤一个Series对象,返回值为布尔Series对象;也可以是行代洗一个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对象,用于将data中匹配标签(Series对象)或匹配列标签(DataFrame对象)所对应的缺失值替换为不同的源码下载值,未与value匹配的data中的缺失值则不会被替换。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值时才会执行删除操作;how缺省时默认为any。dropna的云服务器返回值为删掉缺失值的Series或DataFrame对象。

3)Pandas还为Series和DataFrame提供了interpolate()方法,通过插值法补充缺失的数据点,其语法格式如下:

result=data.interpolate(method=linear,axis=0,…) 

method表示使用的插值方法,缺省时默认为线性插值linear。常用的还有

time,即根据时间间隔进行插值。除此之外,method还提供了更高级的插值方法,比如Scipy库中的nearest、zero、slinear、quadratic、cubic、

spline、barycentric、polynomial等。axis参数的用法与dropna方法相同。

下面通过代码清单演示Pandas提供的处理缺失数据方法的用法。

代码清单 Pandas处理缺失数据方法的用法示例 1 import pandas as pd 2 import numpy as np 3 df = pd.DataFrame({ A: [1, 2.1, np.nan, 4.7, 5.6], B: [.25, np.nan,   np.nan, 4, 12.2]}) 4 print(df:\n,df) 5 print(df中的元素是否为缺失值:\n,pd.isna(df)) 6 df1 = df.fillna(0)#用固定值来填充 7 print(用0填充缺失值后的数据:\n,df1) 8 df2 = df.fillna(value={ A: 1, B: 2}) #将A、B列中的NaN分别替换为1、2 9 print(用字典填充缺失值后的数据:\n,df2) 10 df3 = df.fillna(df.mean()) #用每列的平均值来填充 11 print(用每列的平均值填充缺失值后的数据:\n,df3) 12 df4 = df.dropna() 13 print(删除缺失值后的数据:\n,df4) 14 df5=df.interpolate() 15 print(线性插值法填充缺失值后的数据:\n,df5) 16 df6= df.interpolate(method=polynomial,order=2) 17 print(多项式插值法填充缺失值后的数据:\n,df6) 

程序执行结束后,输出结果如下:

df:     A        B 0  1.0     0.25 1  2.1      NaN 2  NaN      NaN 3  4.7     4.00 4  5.6    12.20 df中的元素是否为缺失值:     A       B 0  False  False 1  False   True 2   True   True 3  False  False 4  False  False 用0填充缺失值后的数据:    A       B 0  1.0   0.25 1  2.1   0.00 2  0.0   0.00 3  4.7   4.00 4  5.6  12.20 用字典填充缺失值后的数据:    A      B 0  1.0   0.25 1  2.1   2.00 2  1.0   2.00 3  4.7   4.00 4  5.6  12.20 用每列的平均值填充缺失值后的数据:     A          B 0  1.00   0.250000 1  2.10   5.483333 2  3.35   5.483333 3  4.70   4.000000 4  5.60  12.200000 删除缺失值后的数据:    A      B 0  1.0   0.25 3  4.7   4.00 4  5.6  12.20 线性插值法填充缺失值后的数据:    A      B 0  1.0   0.25 1  2.1   1.50 2  3.4   2.75 3  4.7   4.00 4  5.6  12.20 多项式插值法填充缺失值后的数据:        A        B 0  1.000000   0.250 1  2.100000  -1.975 2  3.433333  -0.725 3  4.700000   4.000 4  5.600000  12.200 

下面对代码清单中的代码做简要说明。

第3行代码通过字典创建了一个5行2列的DataFrame对象df,其中使用Numpy库中的np.nan设置了几个缺失值,如第4行print函数的输出结果所示。 第5行代码通过isna方法来确认df中的哪些元素是缺失值,返回的结果中,True表示df中对应位置为缺失值,False则表示对应位置为正常值。 第6行代码通过fillna方法使用固定值0对df中的缺失值进行填充,并将返回结果赋值给新的DataFrame对象df1,如第7行print函数的输出结果所示。 第8行代码通过fillna方法使用字典{ A: 1, B: 2}对df中的缺失值进行填充,A列中的NaN填充为1,B列中的NaN填充为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对象。当data是Series对象时,duplicated方法中没有subset参数。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处理重复数据方法的用法示例 1 import pandas as pd 2 df = pd.DataFrame({ brand: [YumYum, YumYum, Indomie, Indomie,   Indomie], style: [cup, cup, cup, pack, pack], rating: [4,   4, 3.5, 15, 5]},index=[a, a, b, c, d]) 3 print(df:\n,df) 4 print(对于全列,df的行中是否存在重复项:\n,df.duplicated()) 5 df1=df.drop_duplicates() 6 print(删除上述重复项后的df:\n,df1) 7 print(对于brand和style列,df的行中是否存在重复项:\n,df.duplicated(subset= [brand, style])) 8 df2=df.drop_duplicates(subset= [brand, style]) 9 print(删除上述重复项后的df:\n,df2) 10 print(df的index是否存在重复项:\n,df.index.duplicated(keep=last)) 11 df3=df[~df.index.duplicated(keep=last)] 12 print(删除index重复项后的df:\n,df3) 

程序执行结束后,输出结果如下:

df:       brand  style   rating a    YumYum    cup      4.0 a    YumYum    cup      4.0 b   Indomie    cup      3.5 c   Indomie   pack     15.0 d   Indomie   pack      5.0 对于全列,df的行中是否存在重复项: a    False a     True b    False c    False d    False dtype: bool 删除上述重复项后的df:       brand   style    rating a    YumYum     cup       4.0 b   Indomie     cup       3.5 c   Indomie    pack      15.0 d   Indomie    pack       5.0 对于brand和style列,df的行中是否存在重复项: a    False a     True b    False c    False d     True dtype: bool 删除上述重复项后的df:       brand   style   rating a    YumYum     cup      4.0 b   Indomie     cup      3.5 c   Indomie    pack     15.0 df的index是否存在重复项: [ True False False False False] 删除index重复项后的df:       brand   style   rating a    YumYum     cup      4.0 b   Indomie     cup      3.5 c   Indomie    pack     15.0 d   Indomie    pack      5.0 

下面对代码清单中的代码做简要说明。

第2行代码通过字典创建了一个5行3列的DataFrame对象df,并设置index参数为[a, a, b, c, d],如第3行print函数的输出结果所示。 第4行代码通过duplicated方法来确认df中是否存在重复数据,采用了默认的参数设置,即根据df的所有列来标识重复数据。对于df中的每一组重复数据,第一次出现的位置标记为False,其他重复出现的位置则标记为True,返回值为Series对象。从print函数的输出结果分析得到,df中的第2行为重复数据。 第5行代码通过drop_duplicates方法删除了第4行代码中确定的重复数据所在的行,并将返回结果赋值给新的DataFrame对象df1,如第6行print函数的输出结果所示。 第7行代码通过duplicated方法来确认df中是否存在重复数据,subset= [brand, style]表示根据df的brand和style两列来标识重复数据。对于df中的每一组重复数据,第一次出现的位置标记为False,其他重复出现的位置则标记为True,返回值为Series对象。从print函数的输出结果分析得到,df中的第2行和第5行为重复数据。 第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行代码得到的布尔数组进行取反操作,即将第1行重复项标记为Fasle,其他项标记为True;然后再利用得到的新布尔数组对df进行切片,截取True对应的行,并将返回结果赋值给新的DataFrame对象df3,如第12行print函数的输出结果所示。

Tips

1)上文介绍的drop_duplicates方法也是在数据的拷贝上进行删除,不会改变原数据。 2)Pandas还提供了del和drop等方法,通过位置索引或标签索引删除数据中的指定行或列。

本文摘编于《Python数据分析与应用》,经出版方授权发布。

分享到:

滇ICP备2023006006号-16