数据挖掘和机器学习中会经常用到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一样可以选择合并的类型,比如并集或者交集。