python/pandas数据挖掘 groupby,聚合

来源:互联网 发布:百知尚行 编辑:程序博客网 时间:2024/06/07 03:31

python/pandas数据挖掘(十四)-groupby,聚合,分组级运算

groupby

import pandas as pddf = pd.DataFrame({'key1':list('aabba'),                  'key2': ['one','two','one','two','one'],                  'data1': np.random.randn(5),                  'data2': np.random.randn(5)})df
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

grouped=df['data1'].groupby(df['key1'])grouped.mean()
  • 1
  • 2

以上的分组键均为Series,实际上分组键可以是任何长度适当的数组

states=np.array(['Ohio','California','California','Ohio','Ohio'])years=np.array([2005,2005,2006,2005,2006])df['data1'].groupby([states,years]).mean()
  • 1
  • 2
  • 3

这里写图片描述

df.groupby('key1').mean()
  • 1

这里写图片描述

可以看出没有key2列,因为df[‘key2’]不是数值数据,所以被从结果中移除。默认情况下,所有数值列都会被聚合,虽然有时可能被过滤为一个子集。

对分组进行迭代

for name, group in df.groupby('key1'):        print (name)        print (group)
  • 1
  • 2
  • 3

这里写图片描述

可以看出name就是groupby中的key1的值,group就是要输出的内容。 
同理:

for (k1,k2),group in df.groupby(['key1','key2']):    print ('===k1,k2:')    print (k1,k2)    print ('===k3:')    print (group)
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

对group by后的内容进行操作,如转换成字典

piece=dict(list(df.groupby('key1')))piece{'a':       data1     data2 key1 key2 0 -0.233405 -0.756316    a  one 1 -0.232103 -0.095894    a  two 4  1.056224  0.736629    a  one, 'b':       data1     data2 key1 key2 2  0.200875  0.598282    b  one 3 -1.437782  0.107547    b  two}piece['a']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里写图片描述

groupby默认是在axis=0上进行分组的,通过设置也可以在其他任何轴上进行分组.

grouped=df.groupby(df.dtypes, axis=1)dict(list(grouped)){dtype('float64'):       data1     data2 0 -0.233405 -0.756316 1 -0.232103 -0.095894 2  0.200875  0.598282 3 -1.437782  0.107547 4  1.056224  0.736629, dtype('O'):   key1 key2 0    a  one 1    a  two 2    b  one 3    b  two 4    a  one
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

选取一个或者一组列

这里写图片描述 
对于大数据,很多情况是只需要对部分列进行聚合

df.groupby(['key1','key2'])[['data2']].mean()
  • 1
  • 2

这里写图片描述

通过字典或者series进行分组

people=pd.DataFrame(np.random.randn(5,5),                   columns=list('abcde'),                   index=['Joe','Steve','Wes','Jim','Travis'])people.ix[2:3,['b','c']]=np.nan #设置几个nanpeople
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

已知列的分组关系

mapping={'a':'red','b':'red','c':'blue','d':'blue','e':'red','f':'orange'}by_column=people.groupby(mapping,axis=1)by_column.sum()
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

如果不加axis=1, 则只会出现 a b c d e

Series 也一样

map_series=pd.Series(mapping)map_seriesa       redb       redc      blued      bluee       redf    orangedtype: objectpeople.groupby(map_series,axis=1).count()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里写图片描述

通过函数进行分组

相较于dic或者Series,python函数在定义分组关系映射时更有创意。任何被当做分组键的函数都会在各个索引上被调用一次,其返回值就会被用作分组名称。假设你按人名的长度进行分组,仅仅传入len即可

people.groupby(len).sum() a b c d e 3 -1.308709 -2.353354 1.585584 2.908360 -1.267162 5 -0.688506 -0.187575 -0.048742 1.491272 -0.636704 6 0.110028 -0.932493 1.343791 -1.928363 -0.364745
  • 1
  • 2

将函数和数组、列表、字典、Series混合使用也不是问题,因为任何东西都会最终转换为数组

 key_list=['one','one','one','two','two'] people.groupby([len,key_list]).sum()
  • 1

根据索引级别进行分组

层次化索引最方便的地方就在于他能够根据索引级别进行聚合。要实现该目的,通过level关键字出入级别编号或者名称即可:

columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],[1,3,5,1,3]],names=['cty','tenor'])hier_df=pd.DataFrame(np.random.randn(4,5),columns=columns)hier_df
  • 1
  • 2
  • 3

这里写图片描述

hier_df.groupby(level='cty',axis=1).count()
  • 1

这里写图片描述

数据聚合

调用自定义的聚合函数

这里写图片描述

这里写图片描述

面向列的多函数应用

对Series或者DataFrame列的聚合运算实际是使用aggregate或者调用mean,std等方法。下面我们想对不同的列使用不同的聚合函数,或者一次应用多个函数

grouped=tips.groupby(['sex','smoker'])grouped_pct=grouped['tip_pct'] #tip_pct列grouped_pct.agg('mean')#对与9-1图标中描述的统计,可以将函数名直接以字符串传入#如果传入一组函数,得到的df的列名就会以相应的函数命名
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

自动给出的列名辨识度低,如果传入的是(name, function)元组组成的列表,则各个元组的第一个元素将被用作df的列名

这里写图片描述

对于df,可以定义一组用于全部列的函数,或在不同的列应用不同的函数 
这里写图片描述

如果想对不同的列应用不同的函数, 具体的办法是想agg传入一个从列名映射到函数的字典 
这里写图片描述 
只有将多个函数应用到至少一列时,df才能拥有层次化的列

分组级运算和转换

聚合只是分组运算的一种,它是数据转换的特列。transform 和apply更牛叉.

transform会将一个函数应用到各个分组,然后将结果放在适当的位置. 如果各分组产生的标量值,则该标量值会被广播出去。

transform也是有严格条件的特殊函数:传入的函数只能产生两种结果,要么产生一个可以广播的标量值(如:np.mean), 要么产生一个相同大小的结果数组。

people=pd.DataFrame(np.random.randn(5,5),                   columns=list('abcde'),                   index=['Joe','Steve','Wes','Jim','Travis'])people
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

key=['one','two','one','two','one']people.groupby(key).mean()
  • 1
  • 2

这里写图片描述

people.groupby(key).transform(np.mean)
  • 1

这里写图片描述

可以看到有很多与表2一样的值。

def demean(arr):    return arr-arr.mean()demeaned=people.groupby(key).transform(demean)demeaned
  • 1
  • 2
  • 3
  • 4
  • 5
demeaned.groupby(key).mean()
  • 1

最一般化的groupby 方法是apply.

tips=pd.read_csv('C:\\Users\\ecaoyng\\Desktop\\work space\\Python\\py_for_analysis_code\\pydata-book-master\\ch08\\tips.csv')tips[:5]
  • 1
  • 2

这里写图片描述

新生成一列

tips['tip_pct']=tips['tip']/tips['total_bill']tips[:6]
  • 1
  • 2

这里写图片描述

根据分组选出最高的5个tip_pct值

def top(df,n=5,column='tip_pct'):    return df.sort_index(by=column)[-n:]top(tips,n=6)
  • 1
  • 2
  • 3

这里写图片描述

对smoker分组并应用该函数

tips.groupby('smoker').apply(top)
  • 1

这里写图片描述

多参数版本

tips.groupby(['smoker','day']).apply(top,n=1,column='total_bill')
  • 1

这里写图片描述

分位数和桶分析

cut and qcut与groupby结合起来,能轻松的对数据集的桶(bucket)或者分位数(quantile)分析。

frame=pd.DataFrame({'data1':np.random.randn(1000),                   'data2': np.random.randn(1000)})frame[:5]
  • 1
  • 2
  • 3

这里写图片描述

factor=pd.cut(frame.data1,4)factor[:10]0    (0.281, 2.00374]1    (0.281, 2.00374]2    (-3.172, -1.442]3     (-1.442, 0.281]4    (0.281, 2.00374]5    (0.281, 2.00374]6     (-1.442, 0.281]7     (-1.442, 0.281]8     (-1.442, 0.281]9     (-1.442, 0.281]Name: data1, dtype: categoryCategories (4, object): [(-3.172, -1.442] < (-1.442, 0.281] < (0.281, 2.00374] < (2.00374, 3.727]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
def get_stats(group):    return {'min':group.min(),'max':group.max(),'count':group.count(),'mean':group.mean()}grouped=frame.data2.groupby(factor)grouped.apply(get_stats).unstack()
  • 1
  • 2
  • 3
  • 4

这里写图片描述

这些都是长度相等的桶,要根据样本分为数得到大小相等的桶,使用qcut即可.

长度相等的桶:区间大小相等 
大小相等的桶:数据点数量相等

grouping=pd.qcut(frame.data1,10,labels=False)#label=false即可值获取分位数的编号grouped=frame.data2.groupby(grouping)grouped.apply(get_stats).unstack()
  • 1
  • 2
  • 3

这里写图片描述

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 雷克萨斯es200怎么样 xvid0es手机版下载 es文件管理 es雷克萨斯报价 雷克萨斯es报价 雷克萨斯es怎么样 雷克萨斯es200价格 蔚来es6补贴后多少钱 雷克萨斯es300h混动 欧美vidi0es洗澡 欧美veid0es高清免费 雷克萨斯es新款 雷克萨斯es300h报价 雷克萨斯es混动 雷克萨斯es200新款 欧美vidi0es2 es350雷克萨斯 蔚来汽车es8 富康es500 es凌志 雷克萨斯多少钱 es文件浏览 es什么意思 雷克萨斯300h 雷克萨斯240 凌志es200报价 雷克萨斯350 rx es是什么意思 雷克萨斯es350报价 es250报价 ls 凌志350报价 nx ex文件浏览器 雷克萨斯论坛 雷克萨斯300 雷克萨斯ex350 雷克萨斯es论坛 雷克萨斯怎么样 雷克萨斯250