R实现分组汇总的几种办法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
R实现分组汇总的几种办法
分组汇总是对二维结构化数据中的某个字段(或多个字段)分组,并对组内字段进行汇总的算法,下面的例子将展示R语言实现分组汇总的几种办法。为了更加通用,例子中的分组字段是2个,汇总算法也是2种。
案例描述:
请将数据框orders按照CLIENT和SELLERID分组,并在组内对AMOUNT字段分别求和、求最大值。
说明:orders存储着订单记录,其来源可以是数据库也可以是文件,比如:
方法1:aggregate函数
代码:
result1<-aggregate(orders$AMOUNT, orders[,c("SELLERID","CLIENT")],sum)
result2<-aggregate(orders$AMOUNT, orders[,c("SELLERID","CLIENT")],max)
result<-cbind(result1,result2$x)
代码解读:
1.从名字就可以看出,aggregate是专用于分组汇总的函数,它的输入参数和计算结果都
是数据框,用法相对简单。
2.aggregate函数不能对分组后的数据进行多种汇总计算,因此要用两句代码分别实现sum
和max算法,最后再用cbind拼合。显然,上述代码在性能和易用性上存在不足。
3.aggregate函数对分组字段的顺序有一个奇怪的要求:必须反向排列。鉴于这个怪要求,
先对CLIENT分组再对SELLERID分组就必须写成:orders[,c("SELLERID","CLIENT")]。如果按照正常的思维习惯写代码,结果将是错误的。
4.不仅代码的写法违反正常的思维习惯,计算后的结果也很怪异:SELLERID字段会排在
CLIENT之前。事实上,为了使计算结果更符合业务逻辑,上述的代码还要继续加工才行。
总结:
aggregate函数勉强可用,但在性能和方便性上存在不足,代码的写法、计算结果、业
务逻辑这三者不一致。
方法2:split+lapply函数
代码:
sp<-split(orders,orders[,c("SELLERID","CLIENT")],drop=TRUE)
result1<-lapply(sp,FUN=function(x) sum(x$AMOUNT))
result2<-lapply(sp,FUN=function(x) max(x$AMOUNT))
result<-cbind(result1,result2)
部分计算结果
1.Split函数的作用是将数据框按照指定字段分组,但不做后续计算。lapply函数可以对每
组数据都执行同样的算法。Split和lapply两者结合可以实现本案例。
2.由于分组后的数据可以复用,因此本算法比aggregate性能更高。
pply函数也不支持多种统计方法,因此也要用两句代码分别实现sum和max算法,
最后再用cbind拼合。另外,本算法还要额外用到split函数,因此在易用性上没有改进,反而是更差了。
4.分组顺序仍然要违反正常的思维习惯,必须反写成:orders[,c("SELLERID","CLIENT")]。
5.计算结果需要大幅加工,很不方便。可以看到,计算结果中的第一列实际上是
“SELLERID.CLIENT”,我们需要把它拆分成两列并调换顺序才行。
总结:
本算法在性能上有所提高,但在易用性上明显不足,在代码写法、业务逻辑、计算结果上仍然存在不一致。
Lapply是apply函数族的一份子,类似的函数还有sapply和tapply。其中sapply的用法和lapply的区别只在参数上,如下:
sp<-split(orders,orders[,c("SELLERID","CLIENT")],drop=TRUE)
result1<-sapply(sp,simplify=FALSE,FUN=function(x) sum(x$AMOUNT))
result2<-sapply(sp,simplify=FALSE,FUN=function(x) max(x$AMOUNT))
result<-cbind(result1,result2)
tapply专用于数据框,按理说最适合解决本案例,但事实并非如此。tapply只对单字段分组适用,在进行双字段联合分组时其结果为二维矩阵,用户还需要进行复杂的处理才行,比如tapply(orders$AMOUNT, orders[,c("SELLERID","CLIENT")],function(x) sum(x)),这句代码的计算结果是:
第三方库函数
用R的内置函数进行分组汇总会存在各种缺点,这时可以考虑用第三方库函数,比如Reshape、stack等。这些第三方库函数的稳定性和计算效率一般不如内置函数,而且资料较少,实现本案例有一定的难度。这里就不再一一列举了。
第三方语言
本案例也可以用Python、集算器、Perl等语言来实现。和R语言一样,这几种语言都可以实现分组汇总以及结构化数据的计算,下面简单介绍集算器和Python的解决方案。
集算器
集算器只需使用groups函数就是实现本案例,语法简洁易懂,符合正常的思维习惯,代码如下:
result=orders.groups(CLIENT,SELLERID;sum(Amount),max(Amount))
Python(pandas)
如果用Python的内置函数直接实现本案例,代码将相当复杂,所以这里用第三方函数库pandas来解决。pandas先用groupby函数来进行分组运算,再用agg函数来进行汇总计算,比R语言简练,但比集算器还略有不足,代码如下:
result= orders.groupby(['CLIENT','SELLERID']).agg({'AMOUNT':[sum,max]})
pandas的计算结果、语法、业务逻辑高度一致,部分计算结果如下: