groupby分组聚合和运算2
本文是对《利用Python进行数据分析》中关于groupby进行分组聚合和运算的一个回顾性总结2。
目录
利用groupby进行数据聚合
分组级运算和转换
透视表
交叉表(了解)
案例
利用groupby进行数据聚合
含义:对于groupby后对象的数据操作,聚合指的是任何能够从数组产生标量值的数据转换过程。
分位数操作quantile
实例:# 此处对于聚合,指的是任何能够从数组 产生标量值的数据转换过程。 除了可以使用mean,count,sum等常见聚合运算外,还可以使用自己创造的聚合运算,还可以调用分组对象上已经定义好的任何方法。 如quantile 可以计算Series 或 DataFrame列的样本分位数 。
df = DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],'key2' : ['one', 'two', 'one', 'two', 'one'],'data1' : np.random.randn(5),'data2' : np.random.randn(5)})
grouped=df.groupby('key1')
grouped['data1'].quantile(0.9)
注意: 虽然quantile 并没有明确的实现于 groupby ,但它是一个Series方法,所以这里是能用的,实际上,groupby 会高效的对Series进行切片,然后对各片调用piece.quantile(0.9),最后将这些结果组装成最终结果
输出
key1
a 1.668413
b -0.523068
Name: data1, dtype: float64
describe函数
实例:统计函数describe会对grouped对象中的各列都进行describe包含的函数操作。
grouped.describe() # 注意,有些方法(如describe)也是可以用在这里的,即使严格来讲,它们并非聚合运算:
常见自带聚合函数
常见的自带的部分聚合函数可以直接用,性能更快。
自定义聚合函数
实例: 使用 自己的聚合函数,只需将其传入aggregate 或 agg 方法即可
# 使用 自己的聚合函数,只需将其传入aggregate 或 agg 方法即可
def peak_to_peak(arr):return arr.max()-arr.min()
grouped.agg(peak_to_peak)
输出
data1 data2
key1
a 2.170488 1.300498
b 0.036292 0.487276
性能:
自定义聚合函数要比表中那些经过优化的函数慢得多。这是因为在构造中间分组数据块时存在非常大的开销(函数调用、数据重排等)。
面向列的多函数应用
对于自定义或者自带的函数都可以用agg传入一次应用多个函数 。传入函数组成的list。所有的列都会应用这组函数。
实例
# 如果使用 你自己的聚合函数,只需将其传入aggregate 或 agg 方法即可
grouped=tips.groupby(['sex','smoker'])
def peak_to_peak(arr):return arr.max()-arr.min()
grouped.agg(peak_to_peak)
# # 可以对不同的列使用不同的聚合函数,或一次应用多个函数
# 如果传入一组函数 或函数名 ,得到的结果DataFrame 的列就会以 相应的函数命名
grouped_pct.agg(['mean','std',peak_to_peak]) #将自带mean函数等也可以用agg传入
输出
#tips数据的前3行
total_bill tip sex smoker day time size tip_pct
0 16.99 1.01 Female No Sun Dinner 2 0.059447
1 10.34 1.66 Male No Sun Dinner 3 0.160542
2 21.01 3.50 Male No Sun Dinner 3 0.166587
mean std peak_to_peak
sex smoker
Female No 0.156921 0.036421 0.195876
Yes 0.182150 0.071595 0.360233
Male No 0.160669 0.041849 0.220186
Yes 0.152771 0.090588 0.674707
对不同的列进行不同的函数操作
传入元素为带着函数的元组的list
实例: 注意如果传入agg 的是一个由(name,function)元组组成的列表,则各元组的第一个元素就会被用作DataFrame的列名(可以将这种二元元组列表看做一个有序映射)
# 并非一定要接受GroupBy自动给出的那些列名,特别是lambda函数,它们的名称是'<lambda>',这样的辨识度就很低了(通过函数的name属性看看就知道了)。因此,如果传入agg 的是一个由(name,function)元组组成的列表,则各元组的第一个元素就会被用作DataFrame的列名(可以将这种二元元组列表看做一个有序映射):
grouped_pct=grouped['tip_pct']
grouped_pct.agg([('foo','mean'),('bar',np.std)]) # 如下面结果列中的列名即元组的第一个元素 .
输出
foo bar
sex smoker
Female No 0.156921 0.036421
Yes 0.182150 0.071595
Male No 0.160669 0.041849
Yes 0.152771 0.090588
以'无层次索引'的形式返回聚合数据
需要在groupby的时候就指定as_index=False。这样就不会根据依据的对象形成层次化索引。默认是为true 。参数 group_keys等价与as_index。
实例1
asind=tips.groupby(['sex','smoker'],as_index=False).mean() # 唯一的分组键组成的索引(可能还是层次化的)。由于并不总是需要如此,所以你可以向groupby传入as_index=False以禁用该功能,这样在应用函数操作grouped对象时,就不会带这分组键作为索引了,而将补充整型值索引,注意 分组的依据将形成列体现在结果中。
print(asind)
输出
sex smoker total_bill tip size tip_pct
0 Female No 18.105185 2.773519 2.592593 0.156921
1 Female Yes 17.977879 2.931515 2.242424 0.182150
2 Male No 19.791237 3.113402 2.711340 0.160669
3 Male Yes 22.284500 3.051167 2.500000 0.152771
实例2
print(tips.groupby(['sex','smoker'],as_index=True).mean()) # 会形成层次化索引
输出
total_bill tip size tip_pct
sex smoker
Female No 18.105185 2.773519 2.592593 0.156921
Yes 17.977879 2.931515 2.242424 0.182150
Male No 19.791237 3.113402 2.711340 0.160669
Yes 22.284500 3.051167 2.500000 0.152771
分组级运算和转换
增加列名后缀,将同后缀的merge到一起,这样将运算的值也带到了后面,实现同放一起看了。
函数:.add_prefix('mean_')
实例:
k1_means = df.groupby('key1').mean().add_prefix('mean_') # 对于聚合后运算对象结果中的列增加后缀名以区分不是原来的属性了
k1_means
原数据df[:3]为:
data1 data2 key1 key2
0 -0.204708 1.393406 a one
1 0.478943 0.092908 a two
2 -0.519439 0.281746 b one
输出:
mean_data1 mean_data2
key1
a 0.746672 0.910916
b -0.537585 0.525384
print(df.head(2))
print(pd.merge(df,k1_means,left_on='key1',right_index=True)) # 将同后缀的merge到一起,这样成功将运算的值也带到了后面,实现同一个看了。
输出
data1 data2 key1 key2
0 -0.20 1.39 a one
1 0.48 0.09 a two
data1 data2 key1 key2 mean_data1 mean_data2
0 -0.20 1.39 a one 0.75 0.910
1 0.48 0.09 a two 0.75 0.910
4 1.97 1.25 a one 0.75 0.910
2 -0.52 0.28 b one -0.54 0.525
3 -0.56 0.77 b two -0.54 0.525
拆分与组合apply
含义: 最一般化的groupby 方法是apply ,apply会将待处理的对象拆分成多个片段,然后对各片段调用传入的函数,最后尝试将各片段组合到一起。
实例
tips=tips.round(2)
print(tips[:3])
# 小费 数据集,根据分组选出最高的 5个tip_pct值
#首先 编写一个选取指定列具有最大值的行的函数
def top(df,n=5,column='tip_pct'):return df.sort_index(by=column)[-n:]
# 如果对smoker 分组,并用该函数调用apply
print(tips.groupby('smoker').apply(top))
上面的运算实质是 top函数在DataFrame的各个片段上调用,然后结果由 pandas.concat 组装到一起,并以分组名称进行了标记。于是,最终结果有了一个层次化的索引,其内层索引值来源于 原 DataFrame
输出
total_bill tip sex smoker day time size tip_pct
0 16.99 1.01 Female No Sun Dinner 2 0.06
1 10.34 1.66 Male No Sun Dinner 3 0.16
2 21.01 3.50 Male No Sun Dinner 3 0.17
total_bill tip sex smoker day time size tip_pct
smoker
No 185 20.69 5.00 Male No Sun Dinner 5 0.24
88 24.71 5.85 Male No Thur Lunch 2 0.24
51 10.29 2.60 Female No Sun Dinner 2 0.25
149 7.51 2.00 Male No Thur Lunch 2 0.27
232 11.61 3.39 Male No Sat Dinner 2 0.29
Yes 109 14.31 4.00 Female Yes Sat Dinner 2 0.28
183 23.17 6.50 Male Yes Sun Dinner 4 0.28
67 3.07 1.00 Female Yes Sat Dinner 1 0.33
178 9.60 4.00 Female Yes Sun Dinner 2 0.42
172 7.25 5.15 Male Yes Sun Dinner 2 0.71
# 如果传给apply的函数能够接受其他参数或关键词,则可将这些内容放在函数名后面一并传入
print(tips.groupby(['smoker','day']).apply(top,n=1,column='total_bill'))
输出
total_bill tip sex smoker day time size tip_pct
smoker day
No Fri 94 22.75 3.25 Female No Fri Dinner 2 0.14
Sat 212 48.33 9.00 Male No Sat Dinner 4 0.19
Sun 156 48.17 5.00 Male No Sun Dinner 6 0.10
Thur 142 41.19 5.00 Male No Thur Lunch 5 0.12
Yes Fri 95 40.17 4.73 Male Yes Fri Dinner 4 0.12
Sat 170 50.81 10.00 Male Yes Sat Dinner 3 0.20
Sun 182 45.35 3.50 Male Yes Sun Dinner 3 0.08
Thur 197 43.11 5.00 Female Yes Thur Lunch 4 0.12
除这些基本用法之外,能否充分发挥apply的威力很大程度上取决于你的创造力。传入的那个函数能做什么全由你说了算,它只需返回一个pandas对象或标量值即可。
禁止分组键
通常情况下,groupby 的分组键 会跟原始对象的索引共同构成 结果对象中的层次化索引。将group_keys=False传入groupby即可禁止这种效果。等价与as_index=False
例子
print(tips.groupby('smoker').apply(top))
print("**"*6)
print(tips.groupby('smoker',group_keys=False).apply(top)) # 这个smoke的值就未出现在索引中了。
print("**"*6)
print(tips.groupby('smoker',as_index=dex=False).apply(top)) # group_keys等价与as_index
分位数和桶
pandas有一些能根据指定面元或样本分位数将数据拆分成多块的工具(比如cut和qcut)。将这些函数跟groupby与apply结合起来,就能非常轻松地实现对数据集的桶(bucket)或分位数(quantile)分析了
注意: 由 cut 返回的 对象可直接用于groupby 。
例子cut
def get_stats(group):return {'min':group.min(),'max':group.max(),'count':group.count(),'mean':group.mean()} # 注意此用字典返回,方便后续用unstack
frame=DataFrame({'data1':np.random.randn(1000),'data2':np.random.randn(1000)})
factor=pd.cut(frame.data1,4) # 等长的桶
grouped=frame.data2.groupby(factor)
print(grouped.apply(get_stats).unstack())
输出
count max mean min
data1
(-2.956, -1.23] 96.0 1.670835 -0.041782 -3.399312
(-1.23, 0.489] 602.0 3.260383 -0.014862 -2.989741
(0.489, 2.208] 291.0 2.954439 0.091055 -3.745356
(2.208, 3.928] 11.0 1.765640 0.055158 -1.929776
例子qcut
# Return quantile numbers
grouping = pd.qcut(frame.data1, 10, labels=False) #qcut ,根据样本分位数 得到大小相等的桶,传入lbels=False 即可值获取分位数的编号。grouped = frame.data2.groupby(grouping) # groupby的依据直接应用qcut划分得到的桶
# print(grouped.apply(get_stats))
grouped.apply(get_stats).unstack() # unstack 转化为桶。
输出
count max mean min
data1
0 100.0 2.146716 -0.061124 -3.018842
1 100.0 2.038456 -0.057383 -2.641014
2 100.0 2.285401 0.082387 -2.453248
3 100.0 2.903300 -0.057825 -2.901831
4 100.0 2.209647 0.007647 -2.251291
5 100.0 2.497837 -0.056052 -3.108915
6 100.0 2.228700 -0.044572 -1.866563
7 100.0 2.430878 0.033692 -3.333767
8 100.0 2.215585 -0.001622 -2.428129
9 100.0 1.716892 -0.079520 -2.494075
填充缺失值
对于groupby后得到的对象中缺失值的填充,apply去应用填充的函数或者关于相应列或行索引与填充值的字典映射
fill_mean=lambda g : g.fillna(g.mean())
data.groupby(group_key).apply(fill_mean) # 可以用分组平均值去填充NA值
fill_values={'East':0.5,'West':-1} # 也可以在代码中预定义各组的填充值。其中East和west均为是分组依据中值(即groupby后形成的索引的一个值
fill_func=lambda g : g.fillna(fill_values[g.name]) # 由于分组具有一个name属性,所以此可以拿来用下。注意此用的g.name. 注意 fill_values里面的key要在groupby 中的值里。
data.groupby(group_key).apply(fill_func)
计算相关性
列与列的相关性
SeriesA.corr(SeriesB)
实例
# Annual correlation of Apple with Microsoft
by_year.apply(lambda g: g['AAPL'].corr(g['MSFT']))
dataframe与列的相关性
dfA.corr(seriesB)
透视表
含义
透视表pivot tables是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具。 它根据一个或多个键对数据进行聚合,并根据行和列上的分组键将数据分配到各个矩形区域中。
在Python和pandas中,groupby功能以及(能够利用层次化索引的)重塑运算制作透视表。DataFrame有一个pivot_table方法,此外还有一个顶级的pandas.pivot_table函数,但pivot_table能更方便。除能为groupby提供便利之外,pivot_table还可以添加分项小计,也叫做margins。
参数
案例
数据准备
print(tips.head(2))
total_bill tip sex smoker day time size tip_pct
0 16.99 1.01 Female No Sun Dinner 2 0.06
1 10.34 1.66 Male No Sun Dinner 3 0.16
# 假设我想要根据day和smoker计算分组平均数(注意pivot_table的默认聚合类型为求平均),并将day和smoker放到行上:
tips=tips.round(2)
print(tips.pivot_table(index=['sex','smoker']))
输出
size tip tip_pct total_bill
sex smoker
Female No 2.592593 2.773519 0.156852 18.105185
Yes 2.242424 2.931515 0.182424 17.977879
Male No 2.711340 3.113402 0.161031 19.791237
Yes 2.500000 3.051167 0.152667 22.284500
# 等价于
tips.groupby(['sex','smoker']).mean().round(2) #用groupby 做. 同上面的结果是一样的(只是排列顺序有差别)
输出
total_bill tip size tip_pct
sex smoker
Female No 18.11 2.77 2.59 0.16
Yes 17.98 2.93 2.24 0.18
Male No 19.79 3.11 2.71 0.16
Yes 22.28 3.05 2.50 0.15
# pivot_table相比groupby能更方便
# 假设我们只想聚合tip_pct和size,而且想根据time进行分组。我将smoker放到列上,把day放到行上: 注意此时用groupby 就不好做了,而此时用pivot_table 很好做
tips.pivot_table(['tip_pct','size'],index=['sex','day'],columns='smoker').round(2)# 注意参数index里表示行的依据
输出
size tip_pct
smoker No Yes No Yes
sex day
Female Fri 2.50 2.00 0.16 0.21
Sat 2.31 2.20 0.15 0.16
Sun 3.07 2.50 0.16 0.24
Thur 2.48 2.43 0.16 0.16
Male Fri 2.00 2.12 0.14 0.14
Sat 2.66 2.63 0.16 0.14
Sun 2.88 2.60 0.16 0.17
Thur 2.50 2.30 0.17 0.16
还可以对这个表作进一步的处理,传入margins=True添加分项小计(默认也是求的平均)。这将会添加标签为All的行和列,其值对应于单个等级中所有数据的分组统计:
tips.pivot_table(['tip_pct','size'],index=['sex','day'],columns='smoker',margins=True) # 这里,All值为平均数:不单独考虑烟民与非烟民(All列),不单独考虑行分组两个级别中的任何单项(All行)。
输出
size tip_pct
smoker No Yes All No Yes All
sex day
Female Fri 2.50 2.00 2.11 0.16 0.21 0.20
Sat 2.31 2.20 2.25 0.15 0.16 0.16
Sun 3.07 2.50 2.94 0.16 0.24 0.18
Thur 2.48 2.43 2.47 0.16 0.16 0.16
Male Fri 2.00 2.12 2.10 0.14 0.14 0.14
Sat 2.66 2.63 2.64 0.16 0.14 0.15
Sun 2.88 2.60 2.81 0.16 0.17 0.16
Thur 2.50 2.30 2.43 0.17 0.16 0.17
All 2.67 2.41 2.57 0.16 0.16 0.16
# 要使用其他的聚合函数而不是求平均,则将函数将其传给aggfunc即可。例如,使用count或len可以得到有关分组大小的交叉表(计数或频率):
tips.pivot_table('tip_pct',index=['sex','smoker'],columns='day',aggfunc=len,margins=True)
输出
day Fri Sat Sun Thur All
time smoker
Dinner No 3.0 45.0 57.0 1.0 106.0Yes 9.0 42.0 19.0 NaN 70.0
Lunch No 1.0 NaN NaN 44.0 45.0Yes 6.0 NaN NaN 17.0 23.0
All 19.0 87.0 76.0 62.0 244.0
# 如果存在空的组合(也就是NA),你可能会希望设置一个fill_value:
tips.pivot_table('size', index=['time', 'sex', 'smoker'],columns='day', aggfunc='sum', fill_value=0)
输出
day Fri Sat Sun Thur
time sex smoker
Dinner Female No 2 30 43 2
Yes 8 33 10 0
Male No 4 85 124 0
Yes 12 71 39 0
Lunch Female No 3 0 0 60
Yes 6 0 0 17
Male No 0 0 0 50
Yes 5 0 0 23
交叉表(了解)
交叉表(cross-tabulation,简称crosstab)是一种用于计算分组频率的特殊透视表。 这个用的少,用到再查吧。
案例
联邦选举委员会数据库的例子(奥巴马与对手的选举数据分析)
根据职业和老板统计赞助信息
对出资额分组
根据洲统计赞助信息
groupby分组聚合和运算2相关推荐
- 【Pandas分组聚合】进阶:透视表、交叉表(pivot_table() 、crosstab())
Pandas透视表.交叉表 创建DataFrame结构 透视表 pivot_table() 单列聚合 多列聚合 交叉表 crosstab() 计算分组频率 两列分组后求第三列的统计指标 创建DataF ...
- Atitit 数据存储的分组聚合 groupby的实现attilax总结
Atitit 数据存储的分组聚合 groupby的实现attilax总结 1. 聚合操作1 1.1. a.标量聚合 流聚合1 1.2. b.哈希聚合2 1.3. 所有的最优计划的选择都是基于现有统计 ...
- pandas数据分组聚合——groupby()、aggregate()、apply()、transform()和filter()方法详解
数据分组 数据分组就是根据一个或多个键(可以是函数.数组或df列名)将数据分成若干组,然后对分组后的数据分别进行汇总计算,并将汇总计算后的结果进行合并,被用作汇总计算的函数称为聚合函数.数据分组的具体 ...
- pandas使用groupby函数进行分组聚合、使用agg函数指定聚合统计计算的数值变量、并自定义统计计算结果的名称(naming columns after aggregation)
pandas使用groupby函数进行分组聚合.使用agg函数指定聚合统计计算的数值变量.并自定义统计计算结果的名称(naming columns after aggregation in dataf ...
- pandas使用groupby函数进行分组聚合并使用agg函数将每个分组特定变量对应的多个内容组合到一起输出(merging content within a specific column of g
pandas使用groupby函数进行分组聚合并使用agg函数将每个分组特定变量对应的多个内容组合到一起输出(merging content within a specific column of g ...
- pandas使用groupby函数对dataframe进行分组统计、使用as_index参数设置分组聚合的结果中分组变量不是dataframe的索引(index)
pandas使用groupby函数对dataframe进行分组统计.使用as_index参数设置分组聚合的结果中分组变量不是dataframe的索引(index) 目录
- pandas使用groupby函数按照多个分组变量进行分组聚合统计、使用agg函数计算分组的多个统计指标(grouping by multiple columns in dataframe)
pandas使用groupby函数按照多个分组变量进行分组聚合统计.使用agg函数计算分组的多个统计指标(grouping by multiple columns in dataframe) 目录
- pandas使用groupby函数、agg函数获取每个分组聚合对应的标准差(std)实战:计算分组聚合单数据列的标准差(std)、计算分组聚合多数据列的标准差(std)
pandas使用groupby函数.agg函数获取每个分组聚合对应的标准差(std)实战:计算分组聚合单数据列的标准差(std).计算分组聚合多数据列的标准差(std) 目录
- pandas使用groupby函数、agg函数获取每个分组聚合对应的均值(mean)实战:计算分组聚合单数据列的均值、计算分组聚合多数据列的均值
pandas使用groupby函数.agg函数获取每个分组聚合对应的均值(mean)实战:计算分组聚合单数据列的均值.计算分组聚合多数据列的均值 目录
- python和R对dataframe的分组聚合操作:dplyr、groupby、agg、group_by、nunique、reset_index、rename、summarise、n_distinct
python和R对dataframe的分组聚合操作:dplyr.groupby.agg.group_by.nunique.reset_index.rename.summarise.n_distinct ...
最新文章
- 不想被问年终奖?2018年春节自救攻略来了!
- 这代码水平,连 Bug 王都甘拜下风 | 每日趣闻
- IBM----Yacc 与 Lex 快速入门
- LeetCode 1845. 座位预约管理系统(set)
- GNS3桥接modem拨号and QOS限速
- python语言应用章节答案_智慧树APPPython语言应用第十单元章节测试答案
- 为什么关于反趋势交易的书以及文章很少?
- Unity移动端使用 Handheld.PlayFullScreenMovie播放视频参数
- Qt QDebug 打印自定义结构体
- 微型计算机原理及应用考试重点,微型计算机原理及应用考试重点.doc
- python卡方拟合优度检验_如何理解拟合优度检验 ?
- 【老骥伏枥-狗年大礼包】嵌入式linux逆向工程,手把手教你作黑Q-第一讲
- 基于JavaEE电子商务交易系统
- Git同时配置github和gitee
- 按键精灵通过抓抓工具来获取坐标位置
- 类型多样的游戏特效网页特效素材,速来收藏
- 电商API数据采集,教你如何获取商品详情数据
- gitee教程(超全,超详细,超长)
- java毕业设计苹果酒店住房管理源码+lw文档+mybatis+系统+mysql数据库+调试
- ue4中隐藏灯光和相机图标_[HDRP]物理灯光是什么?科普向