数据挖掘和机器学习中会经常用到groupby()函数,merge()函数,concat()函数。groupby()函数主要对数据进行聚合,merge()一般情况下用来对两个Dataframe进行结合(一般情况下按照某一列进行将两个Dataframe进行连接),concat()一般情况下是直接在纵轴上面直接合并。下面来总结下这几个函数之间的用法和不同之处。
1.groupby()
1.groupby的一般用法
关于groupby()意为聚合函数,用到最多的就是将同一列中的不同的行的值进行聚合,至于怎么聚合则看后面用什么函数,如函数是mean(),那么表示对这一列进行聚合后其他列的值都进行了求均值,还可以对多个列进行聚合,注意聚合后这些列则成为索引,具体如下:
首先构造一个Dataframe(这里用字典的方法来进行构建Dataframe)
>>>import pandas as pd
>>>df=pd.DataFrame({'s1':['a','a','a','d','e'],
>>> 's2':['one','two','one','four','five'],
>>> 's3': np.random.randn(5),
>>> 's4': np.random.randn(5)})
>>>df
s1 s2 s3 s4
0 a one 0.998368 1.406745
1 a two -0.175247 0.495464
2 a one -0.532833 -0.300619
3 d four -0.019009 0.560179
4 e five 0.815014 -0.251015
1.对df中的s1列进行聚合
>>>a=df.groupby(['s1']).mean()
>>>a
s3 s4
s1
a 0.132566 0.519919
d -0.413402 1.205482
e -1.258209 0.434470
2.对df中的s2列进行聚合
>>>b=df.groupby(['s2']).mean()
>>>b
s3 s4
s2
five -1.258209 0.434470
four -0.413402 1.205482
one -0.454132 1.044133
two 1.305962 -0.528508
在对上面的s1或s2进行聚合后另一列是没有的,因为假如对s1进行聚合那么s2就是麻烦列直接进行在结果中进行删去即取其子集
3.对df中s1和s2列进行聚合,并且选择聚合后的s3列
>>>c=df.groupby(['s1','s2']).mean()['s3']
>>>c
s1 s2
a one -0.454132
two 1.305962
d four -0.413402
e five -1.258209
Name: s3, dtype: float64
4.还可以对其中的series进行聚合,如下
>>>d=df['s3'].groupby(df['s1']).mean()
>>>d
s1
a 0.132566
d -0.413402
e -1.258209
Name: s3, dtype: float64
这里是对s3列进行按照s1列进行聚合,注意这里不能对s2列进行聚合,因为对s1进行聚合则s2列是麻烦列
假如在数据集中某一个列中有很多值是相同的,那么很有可能需要进行聚合处理,一般情况下是是userid这一列有多个值是相同的,那么狠可能对其进行聚合处理,然后对其他列中的值进行计算。
在上面的例子中还可以使用其他的函数,一般使用比较多的函数:
mean() 求均值 |
sum() 求和 |
size() 求某一列中某一个值聚合之前的行数(注意输出的seris即只是一列) |
count() 和上面的series功能类似,但是这里输出的的Dataframe |
describe() 对每个聚合的列求出其count() ,mean(),std(),min(),max(),25%,50%,75%的值 |
std() 标准差 |
frist(),last() 第一个,最后一个非NA值 |
还可以使用groupby来进行迭代,对于多重键的情况,元组的第一个元素将会是由键值组成的元组,如下:
>>>import pandas as pd
>>>df=pd.DataFrame({'s1':['a','a','a','d','e'],
>>> 's2':['one','two','one','four','five'],
>>> 's3': np.random.randn(5),
>>> 's4': np.random.randn(5)})
>>>c=df.groupby(['s1','s2'])
>>>for (k1,k2),group in c:
>>> print (k1, k2)
>>> print (group)
a one
s1 s2 s3 s4
0 a one 0.470365 -0.722192
2 a one -0.453804 0.302290
a two
s1 s2 s3 s4
1 a two -1.22659 -0.761591
d four
s1 s2 s3 s4
3 d four -0.117691 0.99701
e five
s1 s2 s3 s4
4 e five -0.04678 1.081453
2.groupby()中对行进行聚合
在goupby()函数中一般情况下是对Dataframe或者Series进行列聚合,即对某一个或者某几个列中的每一行进行聚合。但是一些特殊的情况也可能对行进行聚合,即对行中的每一列进行聚合,操作就是在groupby中加一个参数axis=1,具体的操作如下:
>>>a=df.groupby(df.dtypes,axis=1)
>>>dict(list(a))
{dtype('float64'): s3 s4
0 -0.359104 0.668434
1 1.305962 -0.528508
2 -0.549160 1.419832
3 -0.413402 1.205482
4 -1.258209 0.434470, dtype('O'): s1 s2
0 a one
1 a two
2 a one
3 d four
4 e five}
2.merge()
merge()是连接两个Dataframe,并且按照某一个列进行连接。首先构造两个Dataframe然后按照其中的某一列进行合并数据集下面首先来构造一个Dataframe:
先构造两个Dataframe
>>>import numpy as np
>>>df1=pd.DataFrame({'s1': np.random.randn(5),
>>> 's2': np.random.randn(5),
>>> 's3': ['1','2','3','4','5'],
>>> 's4': ['a','b','c','d','e']
>>>})
>>>df1
s1 s2 s3 s4
0 a one 0.186894 3.784852
1 a two 0.144526 0.280948
2 a one 0.121664 -0.675135
3 d four -0.747642 -0.114342
4 e five -0.998061 -0.788397
>>>import numpy as np
>>>df2=pd.DataFrame({'s7': ['2','2','2'],
>>> 's6': np.random.randn(3),
>>> 's5': ['one','two','three'],
>>> 's4': ['a','b','c']
>>>})
>>>df2
s7 s6 s5 s4
0 2 0.428500 one a
1 2 0.815716 two b
2 2 1.337478 three c
然后是merge()中常用的参数,前面两个一定是需要进行合并的Dataframe,后面的参数如下,问题具体如下:
on | 两个Dataframe或者series中用于连接的列的名称,必须两个Dataframe中都有 |
how | 表示需要的连接方式:‘inner’(默认);还有,‘outer’、‘left’、‘right’ |
left_on | 左边的Dataframe中用于连接的列的名称 |
right_on | 右边的Dataframe中用于连接的列的名称 |
left_index | 将左侧的行索引用作的连接键 |
right_index | 将右侧的行索引用作的连接键 |
sort | 对合并后是数据按照合并的那一列进行排序 |
suffixes | 字符串值元组,用于追加到重叠列名的末尾,默认为(‘_x’,‘_y’).例如,左右两个DataFrame对象都有‘data’,则结果中就会出现‘data_x’,‘data_y’ |
copy | 设置为False,可以在某些特殊情况下避免将数据复制到结果数据结构中 |
下面对df1和df2中的s4这一列进行连接,使用的是on,注意on是进行两个Dataframe中都有的一列进行连接,如下:
>>>pd.merge(df1,df2,on='s4')
s1_x s2_x s3_x s4 s7_y s6_y s5_y
0 -0.587635 0.942277 1 a 2 -0.534340 one
1 -1.365303 1.346774 2 b 2 -0.225315 two
2 -0.313775 -0.004471 3 c 2 -0.236794 three
3 -0.647611 -0.530852 4 d 2 0.115161 four
4 -1.159848 -0.759894 5 e 2 -0.939340 five
一般情况下on经常和how连用,how='inner'的时候表示交集,how='outer' 的时候表示并集,merge默认的时候是交集,如下
>>>pd.merge(df1,df2,on='s4',how ='inner')
s1 s2 s3 s4 s7 s6 s5
0 1.365108 -0.001064 1 a 2 2.282745 one
1 -0.057489 0.588873 2 b 2 -1.093303 two
2 -0.094838 -0.855097 3 c 2 -0.006426 three
>>>pd.merge(df1,df2,on='s4',how ='outer')
s1 s2 s3 s4 s7 s6 s5
0 1.365108 -0.001064 1 a 2 2.282745 one
1 -0.057489 0.588873 2 b 2 -1.093303 two
2 -0.094838 -0.855097 3 c 2 -0.006426 three
3 0.619130 -0.736540 4 d NaN NaN NaN
4 -0.102612 -0.779650 5 e NaN NaN NaN
如上如果how='outer'那么会按照合并的那一列的并集来进行计算。
还有当how=’left‘的时候那么按照左边这个来连接,how=’right‘的时候按照右边这个来排,如下:
>>>pd.merge(df1,df2,on='s4',how ='left')
s1 s2 s3 s4 s7 s6 s5
0 1.365108 -0.001064 1 a 2 2.282745 one
1 -0.057489 0.588873 2 b 2 -1.093303 two
2 -0.094838 -0.855097 3 c 2 -0.006426 three
3 0.619130 -0.736540 4 d NaN NaN NaN
4 -0.102612 -0.779650 5 e NaN NaN NaN
>>>pd.merge(df1,df2,on='s4',how ='right')
s1 s2 s3 s4 s7 s6 s5
0 1.365108 -0.001064 1 a 2 2.282745 one
1 -0.057489 0.588873 2 b 2 -1.093303 two
2 -0.094838 -0.855097 3 c 2 -0.006426 three
下面还有一种特殊的情况需要使用left_on和right_on ,当两个Dataframe中没有重叠的列的时候,但是某两个列中有相同的元素的时候,那么需要指定左边按照哪一列和右边按照哪一列来进行连接,具体如下:
先构造两个Dataframe
>>>import numpy as np
>>>df1=pd.DataFrame({'a': np.random.randn(5),
>>> 'b': np.random.randn(5),
>>> 'c': ['1','2','3','4','5'],
>>> 'd': ['a','b','c','d','e']
>>>})
>>>df1
a b c d
0 a one 0.186894 3.784852
1 a two 0.144526 0.280948
2 a one 0.121664 -0.675135
3 d four -0.747642 -0.114342
4 e five -0.998061 -0.788397
>>>import numpy as np
>>>df2=pd.DataFrame({'e': ['2','2','2'],
>>> 'f': np.random.randn(3),
>>> 'g': ['one','two','three'],
>>> 'h': ['a','b','c']
>>>})
>>>df2
e f g h
0 2 0.428500 one a
1 2 0.815716 two b
2 2 1.337478 three c
只需要将上面df1和df2列名称修改下来进行演示:
>>>pd.merge(df1,df2,left_on='d',right_on='h')
a b c d e f g h
0 1.232587 0.101968 1 a 2 0.322767 one a
1 0.379328 1.171070 2 b 2 1.597463 two b
2 0.502031 -1.566933 3 c 2 -0.863322 three c
和上面on一样默认是交集假如how='outer'那么是并集:
>>>pd.merge(df1,df2,left_on='d',right_on='h',how='outer')
a b c d e f g h
0 1.232587 0.101968 1 a 2 0.322767 one a
1 0.379328 1.171070 2 b 2 1.597463 two b
2 0.502031 -1.566933 3 c 2 -0.863322 three c
3 -1.535374 -1.224855 4 d NaN NaN NaN NaN
4 0.082348 -0.085027 5 e NaN NaN NaN NaN
left_index和rightx_index是按照左边的Dataframe或者右边的Dataframe的索引来进行连接,如果按照上面的话索引是最前面的序号,操作如下:
>>>pd.merge(df1,df2,left_index=True,right_index=True,how='outer')
a b c d e f g h
0 1.232587 0.101968 1 a 2 0.322767 one a
1 0.379328 1.171070 2 b 2 1.597463 two b
2 0.502031 -1.566933 3 c 2 -0.863322 three c
3 -1.535374 -1.224855 4 d NaN NaN NaN NaN
4 0.082348 -0.085027 5 e NaN NaN NaN NaN
关于sort这个参数默认是True所以这里不多说,suffixes参数是对合并之后的Dataframe可能出现的重复列名进行区分。
3.concat()
concat()可以对Dataframe和series进行结合,下面首先是对series来进行结合,首先是构造series,然后用concat()来进行连接,具体如下:
>>>import pandas as pd
>>>s1=pd.Series([1],index=['a'])
>>>s2=pd.Series([2,3],index=['b','c'])
>>>s3=pd.Series([4],index=['d'])
>>>pd.concat([s1,s2,s3])
a 1
b 2
c 3
d 4
dtype: int64
concat()常用具体的参数如下:
参数 | 含义 |
axis | 默认为0,用来指明连接的轴 |
join | 指定是交集还是并集,inner是交集,outer是并集 |
join_axes | 选择concat后的索引 |
keys | 进行层次化索引 |
names | 用于创建分层级别的名称,如果设置keys或levels的话 |
ignore_index | 设置是否忽略合并后的索引 |
首先构造了一个s1,s2,s3三个series,后下面用concat()将上面三个series按照竖向进行合并,所以concat()中的axis=0,假如axis=1则进行横向合并,axis默认是为0的:
>>>s1=pd.Series([1],index=['a'])
>>>s2=pd.Series([2,3],index=['b','c'])
>>>s3=pd.Series([4],index=['d'])
>>>t=pd.concat([s1,s2,s3],axis=1)
>>>t
0 1 2
a 1.0 NaN NaN
b NaN 2.0 NaN
c NaN 3.0 NaN
d NaN NaN 4.0
需要注意的是将上面 长度不一样的series进行axis=1即横向的合并的时候,假如series的长度不一样那么会将每一个的series进行扩展,因为用concat进行合并的时候是会将所有的索引都包括进行去,所以自然会出现许多的NaN值,我们可以用fillna()函数来将合并后的Dataframe中的NaN来进行替换,具体如下:
>>>t.fillna(1)
0 1 2
a 1.0 1.0 1.0
b 1.0 2.0 1.0
c 1.0 3.0 1.0
d 1.0 1.0 4.0
下面是ignore_index,忽略了上面自己设置的索引,如下:
>>>pd.concat([s1,s2,s3],ignore_index=True)
0 1
1 2
2 3
3 4
dtype: int64
join参数喝前面merge中的how参数类似主要有outer和inner参数,但是这两个参数只有在axis=1的时候才会有效果,具体如下:
>>>s1=pd.Series([1,10],index=['a','b'])
>>>s2=pd.Series([2,3],index=['b','c'])
>>>s3=pd.Series([4,6],index=['d','b'])
>>>pd.concat([s1,s2,s3],axis=1,join='inner')
0 1 2
b 10 2 6
join_axes是选择的索引的名称,如下:
>>>s1=pd.Series([1,10],index=['a','b'])
>>>s2=pd.Series([2,3],index=['b','c'])
>>>s3=pd.Series([4,6],index=['d','b'])
>>>pd.concat([s1,s2,s3],axis=1,join='outer',join_axes=[['a','b']])
0 1 2
a 1 NaN NaN
b 10 2.0 6.0
keys是进行层次化索引,也可以看成将合并的series或者dataframe进行分开,如下:
>>>s1=pd.Series([1,10],index=['a','b'])
>>>s2=pd.Series([2,3],index=['b','c'])
>>>s3=pd.Series([4,6],index=['d','b'])
>>>pd.concat([s1,s2,s3],axis=0,join='outer',keys=['key1','key2','key3'])
key1 a 1
b 10
key2 b 2
c 3
key3 d 4
b 6
dtype: int64
>>>s1=pd.Series([1,10],index=['a','b'])
>>>s2=pd.Series([2,3],index=['b','c'])
>>>s3=pd.Series([4,6],index=['d','b'])
>>>pd.concat([s1,s2,s3],axis=1,join='outer',keys=['key1','key2','key3'])
key1 key2 key3
a 1.0 NaN NaN
b 10.0 2.0 6.0
c NaN 3.0 NaN
d NaN NaN 4.0
3.区别和总结
groupby()主要是用来将同一个文件之中的,将某一列中的元素进行聚合,主要是去除一些重复的值,并且将这些重复的值进行一定的计算,如计算平均值,方差等。concat()是将几个dataframe或者series进行合并,这里可以横的轴进行合并或者按照纵的轴进行合并。merge()是将两个dataframe或者series按照某一个轴进行合并和前面的concat一样可以选择合并的类型,比如并集或者交集。