Press "Enter" to skip to content

两大步骤,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:
‘,df)

 

5 print(‘df中的元素是否为缺失值:
‘,pd.isna(df))

 

6 df1 = df.fillna(0)#用固定值来填充

 

7 print(‘用0填充缺失值后的数据:
‘,df1)

 

8 df2 = df.fillna(value={‘A’: 1, ‘B’: 2}) #将A、B列中的NaN分别替换为1、2

 

9 print(‘用字典填充缺失值后的数据:
‘,df2)

 

10 df3 = df.fillna(df.mean()) #用每列的平均值来填充

 

11 print(‘用每列的平均值填充缺失值后的数据:
‘,df3)

 

12 df4 = df.dropna()

 

13 print(‘删除缺失值后的数据:
‘,df4)

 

14 df5=df.interpolate()

 

15 print(‘线性插值法填充缺失值后的数据:
‘,df5)

 

16 df6= df.interpolate(method=’polynomial’,order=2)

 

17 print(‘多项式插值法填充缺失值后的数据:
‘,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:
‘,df)

 

4 print(‘对于全列,df的行中是否存在重复项:
‘,df.duplicated())

 

5 df1=df.drop_duplicates()

 

6 print(‘删除上述重复项后的df:
‘,df1)

 

7 print(‘对于brand和style列,df的行中是否存在重复项:
‘,df.duplicated(subset= [‘brand’, ‘style’]))

 

8 df2=df.drop_duplicates(subset= [‘brand’, ‘style’])

 

9 print(‘删除上述重复项后的df:
‘,df2)

 

10 print(‘df的index是否存在重复项:
‘,df.index.duplicated(keep=’last’))

 

11 df3=df[~df.index.duplicated(keep=’last’)]

 

12 print(‘删除index重复项后的df:
‘,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函数的输出结果所示。

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注