groupby()是pandas库中DataFrame结构的函数,最近在看用Movielens数据集进行关联分析的教程时,发现用到了groupby()函数,觉得该函数功能很强大,经常用在for循环结构中用于提取数据,故对该函数一些常用的方法进行一些记录。
先创建一个DataFrame对象df
import pandas as pd df=pd.DataFrame({'name':['a','b','c','d','e'],'age':[10,15,20,15,20],'sex':[True,True,False,True,False]}) df >>> name age sex 0 a 10 True 1 b 15 True 2 c 20 False 3 d 15 True 4 e 20 False依据某个columns对整个DataFrame对象分组
df_1=df.groupby(df['sex']) list(df_1) >>> [(False, name age sex 2 c 20 False 4 e 23 False), (True, name age sex 0 a 10 True 1 b 15 True 3 d 17 True)]依据某个columns对另一个columns数据分组
df_1=df['age'].groupby(df['sex']) list(df_1) >>> [(False, 2 20 4 23 Name: age, dtype: int64), (True, 0 10 1 15 3 17 Name: age, dtype: int64)]这个过程还有另外一种语法
df_1=df.groupby(df['sex'])['age'] list(df_1) >>> [(False, 2 20 4 23 Name: age, dtype: int64), (True, 0 10 1 15 3 17 Name: age, dtype: int64)]当然,也可以同时对多个columns数据进行分组,以第一种语法方式为例,此时要注意多个columns的书写方式
df_1=df[['age','name']].groupby(df['sex']) list(df_1) >>> [(False, age name 2 20 c 4 23 e), (True, age name 0 10 a 1 15 b 3 17 d)]也可以依据多个columns对某个columns数据分组,注意这里groupby函数内columns的写法,不能再像上面那样了
df_1=df['name'].groupby([df['sex'],df['age']]) list(df_1) >>> [((False, 20), 2 c Name: name, dtype: object), ((False, 23), 4 e Name: name, dtype: object), ((True, 10), 0 a Name: name, dtype: object), ((True, 15), 1 b Name: name, dtype: object), ((True, 17), 3 d Name: name, dtype: object)]除了依据DataFrame结构中已有的columns对数据进行分组,还可以通过外部设定的columns对DataFrame数据进行分组
import numpy as np education=np.array(['mid school','high school','university','high school','university']) df_1=df.groupby([education]) list(df_1) >>> [('high school', name age sex 1 b 15 True 3 d 17 True), ('mid school', name age sex 0 a 10 True), ('university', name age sex 2 c 20 False 4 e 23 False)]通过groupby函数来分组时,还有一些别具创意的分组方式,任何被当做分组键的函数都会在各个索引值上被调用一次,其返回值就会被用作分组名称。例如对于所用的df,给它加上索引值index(国籍),然后依据国家名称英文字符的个数来分组
df.index=['China','Russia','USA','English','Japan'] df.groupby(len).sum() >>> age sex 3 20 False 5 30 True 6 15 True 7 15 True可以看到, ‘China’和'Japan'字母长度均为5,故在计算‘age’和'sex'时将其对应的值求和了,'age'不具有求和性质,未参与计算。
在上面的程序中,index的输出为 ['False' , 'True'],group的输出结果为 [ ['20','20'] , ['10','15','15'] ]。一种常见的情况为用index、group的值生成字典。
dic=dict((index,frozenset(group.values))for index,group in df.groupby(df['sex'])['age']) dic >>> {False: frozenset({20}), True: frozenset({10, 15})}在生成字典时,也会有多重键的情况,可以用以下方式
dic=dict(((index_1,index_2),frozenset(group.values))for (index_1,index_2),group in df['age'].groupby([df['sex'],df['age']])) dic >>> {(False, 20): frozenset({20}), (True, 10): frozenset({10}), (True, 15): frozenset({15})}也可以用这种更为简洁的方式
dic=dict((index,frozenset(group.values))for index,group in df['age'].groupby([df['sex'],df['age']])) dic >>> {(False, 20): frozenset({20}), (True, 10): frozenset({10}), (True, 15): frozenset({15})}还有另一种方式来生成字典
dic=dict( list(df.groupby('sex'))) dic >>> {False: name age sex 2 c 20 False 4 e 20 False, True: name age sex 0 a 10 True 1 b 15 True 3 d 15 True} dic[False]['name'] >>> 2 c 4 e Name: name, dtype: object这种对整个df生成字典的方式,字典每个键对应的值仍然为一个DataFrame结构。按照这种方式当然也可以用df中某个columns 生成字典。
数据处理时经常在groupby之后用到求和、平均计算,所以这里也顺带提一下。
计算平均的过程为
df.groupby('sex')['age'].mean() >>> sex False 20.000000 True 13.333333 Name: age, dtype: float64求和的过程为
df.groupby('sex')['age'].sum() >>> sex False 40 True 40 Name: age, dtype: int64还有一种就是对DataFrame整个结构中各行或各列计算平均或求和,这里先引入pandas中轴(axis)的定义,在DataFrame中有axis=0和axis=1两种情况,axis=0表示遍历所有的行,不能理解为axis=0表示对列的操作,同样的,axis=1表示遍历所有的列。另外,在numpy库中也有关键字axis,且用法与pandas中一致。那么通过使用axis,求和、计算平均的过程可以为
df.sum(axis=1) >>> 0 11.0 1 16.0 2 20.0 3 16.0 4 20.0 dtype: float64 df.sum(axis=0) >>> name abcde age 80 sex 3 dtype: object df.mean(axis=0) >>> age 16.0 sex 0.6 dtype: float64