本文主要是介绍一文过pandas入门(中篇)——才疏学浅的莫笑天,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本篇核心内容为数据清洗。
数据清洗
数据工作的步骤应该为:
数据获取 数据清洗 数据分析 数据可视化与建模 因此,上一篇博文中,本人说过,下一篇博文会讲一下数据分析中重要的一步 我们要知道,数据清洗本着为下一步数据分析服务的目的进行,因此,数据处理要根据数据分析确定它是否需要处理,需要怎样的处理,才能适应接下来的分析工作和挖掘工作。
整体分为几个不同的步骤来看。
import pandas as pd
import numpy as np
一. 缺失数据的处理
整体的处理方法在理论上我们可以采用填补或者丢弃。选择哪种依情况而定。总体工作对于pandas来说,就利用四个方法:
fillna():填充 dropna():根据条件筛选过滤 isnull():判断是否为空 notnull():判断是否不为空
如上四个函数,加上我们其他的语法,逻辑等,基本可以完成这一步工作。如下做演示,这几个方法不需要特别讲解
df = pd. DataFrame( [ np. random. rand( 3 ) , np. random. rand( 3 ) , np. random. rand( 3 ) ] , columns= [ 'A' , 'B' , 'C' ] )
df
A B C 0 0.902598 0.598310 0.169824 1 0.425368 0.805950 0.677491 2 0.830366 0.305227 0.487216
df[ 'A' ] [ 0 ] = np. NAN
print ( df)
df. fillna( 1 )
A B C
0 NaN 0.598310 0.169824
1 0.425368 0.805950 0.677491
2 0.830366 0.305227 0.487216
A B C 0 1.000000 0.598310 0.169824 1 0.425368 0.805950 0.677491 2 0.830366 0.305227 0.487216
df[ 'A' ] [ 0 ] = np. NAN
print ( df)
df. dropna( )
A B C
0 NaN 0.598310 0.169824
1 0.425368 0.805950 0.677491
2 0.830366 0.305227 0.487216
A B C 1 0.425368 0.805950 0.677491 2 0.830366 0.305227 0.487216
df[ 'A' ] [ 0 ] = np. NAN
print ( df)
df. dropna( axis= 1 )
A B C
0 NaN 0.598310 0.169824
1 0.425368 0.805950 0.677491
2 0.830366 0.305227 0.487216
B C 0 0.598310 0.169824 1 0.805950 0.677491 2 0.305227 0.487216
bool_df_t = df. isnull( )
bool_df_t
A B C 0 True False False 1 False False False 2 False False False
bool_df = df. notnull( )
bool_df
A B C 0 False True True 1 True True True 2 True True True
当然它也可以完成类似于numpyarray中的操作,不过没啥意义。
print ( df[ bool_df_t] )
print ( df[ bool_df] )
A B C
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaNA B C
0 NaN 0.598310 0.169824
1 0.425368 0.805950 0.677491
2 0.830366 0.305227 0.487216
二. 重复值的处理
考虑到某些数据不符合我们的分析要求,或者输入建模的问题,需要在某种情况下对数据进行重复值的处理
df_obj = pd. DataFrame( { 'data1' : [ 'a' ] * 4 + [ 'b' ] * 4 , 'data2' : np. random. randint( 0 , 4 , 8 ) } )
print ( df_obj)
print ( df_obj. duplicated( ) )
data1 data2
0 a 1
1 a 2
2 a 2
3 a 0
4 b 1
5 b 1
6 b 1
7 b 1
0 False
1 False
2 True
3 False
4 False
5 True
6 True
7 True
dtype: bool
print ( df_obj. duplicated( 'data2' ) )
0 False
1 False
2 True
3 False
4 True
5 True
6 True
7 True
dtype: bool
判断之后,可以利用drop_duplicates()方法删除重复的行。
df_obj. drop_duplicates( )
三. 数据格式转化
考虑到部分数据格式的存在可能不符合后期数据分析的标准,或者不适合作为模型的输入,我们要对某些数据做对应的处理。
利用函数进行映射。 直接指定值进行替换处理。
ser_obj = pd. Series( np. random. randint( 0 , 10 , 10 ) )
ser_obj
0 0
1 0
2 7
3 3
4 0
5 8
6 6
7 7
8 8
9 9
dtype: int32
ser_obj. map ( lambda x : x ** 2 )
0 0
1 0
2 49
3 9
4 0
5 64
6 36
7 49
8 64
9 81
dtype: int64
data = pd. Series( np. random. randint( 0 , 100 , 10 ) )
print ( data)
0 73
1 18
2 48
3 27
4 1
5 60
6 59
7 38
8 66
9 53
dtype: int32
data = data. replace( 73 , 100 )
data
0 100
1 18
2 48
3 27
4 1
5 60
6 59
7 38
8 66
9 53
dtype: int32
data = data. replace( [ 100 , 18 ] , [ - 1 , - 1 ] )
data
0 -1
1 -1
2 48
3 27
4 1
5 60
6 59
7 38
8 66
9 53
dtype: int64
字符串操作,可直接继承python基本语法的字符串操作,这里不在浪费时间。
四. 数据合并
根据不同的条件将数据进行联合。主要使用的方法是pd.merge
pd.merge:(left, right, how=‘inner’,on=None,left_on=None, right_on=None )
left:合并时左边的DataFrame
right:合并时右边的DataFrame
how:合并的方式,默认’inner’, ‘outer’, ‘left’, ‘right’
on:需要合并的列名,必须两边都有的列名,并以 left 和 right 中的列名的交集作为连接键
left_on: left Dataframe中用作连接键的列
right_on: right Dataframe中用作连接键的列
四种连接方式非常重要,它们分别为内连接,全连接,左连接,右连接。
内连接:根据指定键的交集进行连接。 外连接:根据指定键的并集进行连接。 左连接:根据指定left的dataframe键进行连接。 右连接:根据指定right的dataframe的键进行连接。
import pandas as pd
import numpy as npleft = pd. DataFrame( { 'key' : [ 'K0' , 'K1' , 'K2' , 'K3' ] , 'A' : [ 'A0' , 'A1' , 'A2' , 'A3' ] , 'B' : [ 'B0' , 'B1' , 'B2' , 'B3' ] } ) right = pd. DataFrame( { 'key' : [ 'K0' , 'K1' , 'K2' , 'K3' ] , 'C' : [ 'C0' , 'C1' , 'C2' , 'C3' ] , 'D' : [ 'D0' , 'D1' , 'D2' , 'D3' ] } )
left
key A B 0 K0 A0 B0 1 K1 A1 B1 2 K2 A2 B2 3 K3 A3 B3
right
key C D 0 K0 C0 D0 1 K1 C1 D1 2 K2 C2 D2 3 K3 C3 D3
pd. merge( left, right, on= 'key' )
key A B C D 0 K0 A0 B0 C0 D0 1 K1 A1 B1 C1 D1 2 K2 A2 B2 C2 D2 3 K3 A3 B3 C3 D3
left = pd. DataFrame( { 'key1' : [ 'K0' , 'K0' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K1' , 'K0' , 'K1' ] , 'A' : [ 'A0' , 'A1' , 'A2' , 'A3' ] , 'B' : [ 'B0' , 'B1' , 'B2' , 'B3' ] } ) right = pd. DataFrame( { 'key1' : [ 'K0' , 'K1' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K0' , 'K0' , 'K0' ] , 'C' : [ 'C0' , 'C1' , 'C2' , 'C3' ] , 'D' : [ 'D0' , 'D1' , 'D2' , 'D3' ] } )
left
key1 key2 A B 0 K0 K0 A0 B0 1 K0 K1 A1 B1 2 K1 K0 A2 B2 3 K2 K1 A3 B3
right
key1 key2 C D 0 K0 K0 C0 D0 1 K1 K0 C1 D1 2 K1 K0 C2 D2 3 K2 K0 C3 D3
pd. merge( left, right, on= [ 'key1' , 'key2' ] )
key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K1 K0 A2 B2 C1 D1 2 K1 K0 A2 B2 C2 D2
look,如上所示,内连接的方法是连接交集,对于k1 k0这个序列,在right中,显然存在两组数据,而left中只存在一组数据,根据交集来看,这两组数据与那一组数据都属于交集,因此,拼接为两组数据。那如果是left中存在两组呢,我们来看看结果。
left = pd. DataFrame( { 'key1' : [ 'K0' , 'K1' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K0' , 'K0' , 'K1' ] , 'A' : [ 'A0' , 'A1' , 'A2' , 'A3' ] , 'B' : [ 'B0' , 'B1' , 'B2' , 'B3' ] } ) right = pd. DataFrame( { 'key1' : [ 'K0' , 'K1' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K0' , 'K0' , 'K0' ] , 'C' : [ 'C0' , 'C1' , 'C2' , 'C3' ] , 'D' : [ 'D0' , 'D1' , 'D2' , 'D3' ] } )
print ( pd. merge( left, right, on= [ 'key1' , 'key2' ] ) )
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A1 B1 C1 D1
2 K1 K0 A1 B1 C2 D2
3 K1 K0 A2 B2 C1 D1
4 K1 K0 A2 B2 C2 D2
我们来思考一下合并的规则,对于如上数据,我们最终得到5条数据,实际上left和right匹配的数据仅仅只有,一组k0 k0,两组k1 k0罢了,但是这两组k1 k0却进行了交集运算,将数据合并为四组,这种交集运算其实不难理解,但是初次接触也需要思考这其实是数据库交集的计算。可以从如下例子入手。
left = pd. DataFrame( { 'key' : [ 'c' , 'd' , 'c' ] , 'A' : [ 'a' , 'b' , 'e' ] , 'B' : [ 'a' , 'b' , 'e' ] } ,
)
right = pd. DataFrame( { 'key' : [ 'c' , 'd' , 'c' ] , 'C' : [ 'a' , 'b' , 'c' ] , 'D' : [ 'a' , 'b' , 'c' ] } ,
)
left
right
pd. merge( left, right, on= [ 'key' ] )
key A B C D 0 c a a a a 1 c a a c c 2 c e e a a 3 c e e c c 4 d b b b b
left = pd. DataFrame( { 'key1' : [ 'K0' , 'K0' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K1' , 'K0' , 'K1' ] , 'A' : [ 'A0' , 'A1' , 'A2' , 'A3' ] , 'B' : [ 'B0' , 'B1' , 'B2' , 'B3' ] } )
right = pd. DataFrame( { 'key1' : [ 'K0' , 'K1' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K0' , 'K0' , 'K0' ] , 'C' : [ 'C0' , 'C1' , 'C2' , 'C3' ] , 'D' : [ 'D0' , 'D1' , 'D2' , 'D3' ] } )
print ( pd. merge( left, right, how= 'left' , on= [ 'key1' , 'key2' ] ) )
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
3 K2 K0 NaN NaN C3 D3
print ( pd. merge( left, right, how= 'right' , on= [ 'key1' , 'key2' ] ) )
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
3 K2 K0 NaN NaN C3 D3
外连接,所有值,不存在则用na填充(并集)
left = pd. DataFrame( { 'key1' : [ 'K0' , 'K0' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K1' , 'K0' , 'K1' ] , 'A' : [ 'A0' , 'A1' , 'A2' , 'A3' ] , 'B' : [ 'B0' , 'B1' , 'B2' , 'B3' ] } )
right = pd. DataFrame( { 'key1' : [ 'K0' , 'K1' , 'K1' , 'K2' ] , 'key2' : [ 'K0' , 'K0' , 'K0' , 'K0' ] , 'C' : [ 'C0' , 'C1' , 'C2' , 'C3' ] , 'D' : [ 'D0' , 'D1' , 'D2' , 'D3' ] } )
print ( pd. merge( left, right, how= 'outer' , on= [ 'key1' , 'key2' ] ) )
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN
5 K2 K0 NaN NaN C3 D3
处理列名重复数据
df_obj1 = pd. DataFrame( { 'key' : [ 'b' , 'b' , 'a' , 'c' , 'a' , 'a' , 'b' ] , 'data' : np. random. randint( 0 , 10 , 7 ) } )
df_obj2 = pd. DataFrame( { 'key' : [ 'a' , 'b' , 'd' ] , 'data' : np. random. randint( 0 , 10 , 3 ) } )
df_obj1
key data 0 b 4 1 b 5 2 a 3 3 c 0 4 a 4 5 a 5 6 b 4
df_obj2
print ( pd. merge( df_obj1, df_obj2, on= 'key' , suffixes= ( '_left' , '_right' ) ) )
key data_left data_right
0 b 4 7
1 b 5 7
2 b 4 7
3 a 3 8
4 a 4 8
5 a 5 8
df_obj1 = pd. DataFrame( { 'key' : [ 'b' , 'b' , 'a' , 'c' , 'a' , 'a' , 'b' ] , 'data1' : np. random. randint( 0 , 10 , 7 ) } )
df_obj2 = pd. DataFrame( { 'data2' : np. random. randint( 0 , 10 , 3 ) } , index= [ 'a' , 'b' , 'd' ] )
key data1 data2
0 b 4 8
1 b 0 8
6 b 1 8
2 a 6 1
4 a 4 1
5 a 2 1
df_obj1
key data1 0 b 4 1 b 0 2 a 6 3 c 1 4 a 4 5 a 2 6 b 1
df_obj2
pd. merge( df_obj1, df_obj2, left_on= 'key' , right_index= True )
key data1 data2 0 b 4 8 1 b 0 8 6 b 1 8 2 a 6 1 4 a 4 1 5 a 2 1
pd.concat()方法
类似于np.concat,连接数组,这里则是连接dataframe。
df1 = pd. DataFrame( np. arange( 6 ) . reshape( 3 , 2 ) , index= list ( 'abc' ) , columns= [ 'one' , 'two' ] ) df2 = pd. DataFrame( np. arange( 4 ) . reshape( 2 , 2 ) + 5 , index= list ( 'ac' ) , columns= [ 'three' , 'four' ] )
df1
df2
pd. concat( [ df1, df2] )
one two three four a 0.0 1.0 NaN NaN b 2.0 3.0 NaN NaN c 4.0 5.0 NaN NaN a NaN NaN 5.0 6.0 c NaN NaN 7.0 8.0
pd. concat( [ df1, df2] , axis= 1 )
one two three four a 0 1 5.0 6.0 b 2 3 NaN NaN c 4 5 7.0 8.0
pd. concat( [ df1, df2] , axis= 1 , join= 'inner' )
one two three four a 0 1 5 6 c 4 5 7 8
数据的重塑
df_obj = pd. DataFrame( np. random. randint( 0 , 10 , ( 5 , 2 ) ) , columns= [ 'data1' , 'data2' ] ) stacked = df_obj. stack( )
data1 data2
0 5 3
1 7 4
2 5 7
3 7 2
4 9 5
0 data1 5data2 3
1 data1 7data2 4
2 data1 5data2 7
3 data1 7data2 2
4 data1 9data2 5
dtype: int32
df_obj
data1 data2 0 5 3 1 7 4 2 5 7 3 7 2 4 9 5
stacked
0 data1 5data2 3
1 data1 7data2 4
2 data1 5data2 7
3 data1 7data2 2
4 data1 9data2 5
dtype: int32
如上,数据索引变成了层级索引。
print ( type ( df_obj) )
print ( type ( stacked) )
<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.series.Series'>
stacked. unstack( )
data1 data2 0 5 3 1 7 4 2 5 7 3 7 2 4 9 5
整体再来整理一下。
为什么要进行数据清洗?是为了后续的数据分析,建模等操作的方便执行。 数据清洗在数据分析工作的哪一步?在数据分析工作前,为数据分析,模型服务。 数据清洗的流程? 分为几大类:
1. 进行缺失值处理
2. 进行重复值处理
3. 进行数据格式转化
4. 进行数据合并
ok,今天到这里了,本人不准备专门为时间序列结构出一篇博客,所以打算直接将它渗透到后期的实战中,在实战之前还需要补充一些统计学的知识,感谢大家的关注。同学习python的同学可以博主微信,有问题直接交流。
这篇关于一文过pandas入门(中篇)——才疏学浅的莫笑天的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!