天天看点

R语言和集算器:找出每个月的销售额均在前3名的销售员

R语言和集算器都具备优秀的分步运算能力,但在细节上有所不同,下面通过一个例子进行对比:

某公司的销售部门希望统计出优秀的销售员,即今年从1月份到上个月为止,每个月的销售额均是前3名的销售员。数据主要来自MSSQL数据库的订单表:salesOrder,主要字段包括订单编号:orderID,销售员姓名:name,销售额:sales,订单时间:salesDate。

解法大概是这样的:

1.      计算出年初和本月初的日期,按时间过滤出数据

2.      按月份和销售员分组,计算每个月每个销售员的销售额。

3.      按月份分组。计算分组内的销售额的排名。

4.      过滤每个分组内的前3名。

5.      求各分组的交集,即每个月都是前3名的销售员。

R的解法如下:

01   library(RODBC)

02   odbcDataSources()

03   conn<-odbcConnect("sqlsvr")

04   originalData<-sqlQuery(conn,'select *from salesOrder')

05   odbcClose(conn)

06  starTime<-as.POSIXlt(paste(format(Sys.Date(),'%Y'),'-01-01',sep=''))

07  endTime<-as.POSIXlt(paste(format(Sys.Date(),'%Y'),format(Sys.Date(),'%m'),'01',sep='-'))

08   fTimeData<-subset(originalData,salesDate>=starTime& salesDate<endTime)

09  gNameMonth<-aggregate(fTimeData$sales,list(fTimeData$name,format(fTimeData$salesDate,'%m')),sum)

10  names(gNameMonth)<-c('name','month','monthSales')

11   gNameMonth$rank <- do.call(c,tapply(gNameMonth$monthSales, gNameMonth$month,function(x) rank(-x)) )

12   rData<-subset(gNameMonth,rank<=3)

13   nameList <- split(rData$name,rData$month)

14   Reduce(intersect, nameList)

下面是集算器的写法:

R语言和集算器:找出每个月的销售额均在前3名的销售员

下面比较一下二者的解法,先看数据库访问

R语言在Line01-05进行了数据访问,步骤稍多,不过作为常规操作这还是可以接受的。集算器在cell A1可以直接写SQL,非常方便。两者在数据库访问方面有所区别,但差距并不明显,都算得上方便。

再比较下时间函数。

R语言在line06-07计算了本年年初时间和本月月初时间,这里可以看到R语言具备丰富的基本函数。集算器在A2和B2完成了同样的计算,其中pdate函数可以直接求月初日期,相当方便。 两者在时间函数方面看似esProc略胜一筹,但R语言有庞大的第三方函数库,也许有更好用的时间函数。

重点看看分步运算。

首先是按时间过滤,再按月份和销售员分组并汇总销售额。R语言在line 8-9,集算器在cell A3-A4分别实现了上述功能,区别不大。继续计算。按照直接一些的分析思路,接下来应当是: 1.按月份分组;2.在分组内加排名字段并计算排名;3.按排名过滤,只留下每组的前3名;4.最后求各组数据的交集。

R语言的代码在line10-14,顺序是:2->3->1->4。即先在整表中给每个分组内的数据做排名,再分组,注意到没?虽然是分组内的排名,但居然要先排名再分组!出现这一情况的原因是R语言在分组后再加工方面能力比较弱。勉强写成1->2->3->4则需要高超的技巧和复杂的循环表达式,采用逆向思维则使代码大大简化。

集算器在cell A5-A8进行了类似的计算,不需要逆向思维,直观地按照1->2->3->4的顺序就可以了。这是由于esProc提供了~这种巧妙的表达方式,它代表集合中参与运算的当前成员。对于这个例子来说,~是分组中的每一个二维表(相当于R 语言中的data.frame或者SQL中的resutSet)。这样一来~.monthSales就可以表示当前二维表中的某一列。R语言只能用循环等复杂的方式来访问”当前成员”,当然要麻烦许多。

这一项,集算器看起来更直观,优势较大。

再看看查看中间结果的能力。

R语言通过RStudio等工具,可以随时点击变量名查看每一步骤的结果。集算器只有一种官方工具,点击单元格可以看到这一步的结果。能力上2者相差不大,考虑到R语言众多的第三方工具,也许有更好的观察结果的工具。

接着我们比较一下引用计算结果的能力。R语言只要给每一步的计算结果定义一个变量,在以后的步骤中就可以方便地引用。集算器同样可以定义变量来引用,不过直接使用格名做变量名也许更方便,省去了挖空心思想名字的烦恼。

再比较一下交集的计算。最后一步求各组数据的交集,R语言提供了底层的intersect函数,配合Reduce可以计算多组数据的交集。集算器提供了isect函数,直接可以进行多集合的交集运算,也很方便。相比之下,但R语言的Reduce函数想象空间更大,不过esProc更简明些。

由上面的例子可以看出,R语言具备丰富的基础函数和巨大的第3方库函数。集算器在数据成员访问方面提供了优秀的表达方式,尤其是多层次的分组;R语言更多的是依靠循环语句。交互能力上2者均有出色的表现。

继续阅读