行间计算很常见,累计,同期比,环比这些都会涉及到。R语言和集算器都有很好的行间计算能力,但又略有区别。
下面这个案例涉及一些基本的行间运算,可以通过它说明二者的区别:
某公司的销售部门希望统计出优秀的销售员,即给公司提供前一半销售额的销售员。数据主要来自MSSQL数据库的订单表:salesOrder,主要字段包括订单编号:orderID,销售员姓名:name,销售额:sales,订单时间:salesDate。
比较直观的解法是:
1.先按销售员汇总,求得每个销售员的销售额.
2.将上一步的数据按照销售额逆序排序
3.在上一步中求各条记录的累计值。并求出比较标准:公司销售总额的一半。
4.找到上一步中累计值能符合以下条件的销售员的列表:小于等于比较标准;或者虽然大于比较标准,但上一个销售员是小于比较标准的。
R语言的具体解法是这样的:
01library(RODBC)
02odbcDataSources()
03conn<-odbcConnect("sqlsvr")
04originalData<-sqlQuery(conn,'select * from salesOrder')
05odbcClose(conn)
06 nameSum<-aggregate(originalData$sales,list(originalData$name),sum)
07names(nameSum)<-c('name','salesSum')
08orderData<-nameSum[rev(order(nameSum$salesSum)),]
09halfSum<-sum(orderData$salesSum)/2
10orderData$addup<-cumsum(orderData$salesSum)
11 subset(orderData,addup<=halfSum| (addup>halfSum & c( 0, addup[- length (addup)]) <halfSum))
下面是集算器的解法:
先看看计算累计值有什么不同:
R语言在line 10使用 cumsum求累计值。
集算器在A4格使用cumulate求累计值。
两者写法都很方便,但esProc的运算原理是针对每条纪录,先算一遍cumulate,然后按照行号#取得这条纪录对应的累计值。而R语言是只计算一遍,因此效率上比集算器高。
把集算器的这句拆成两句可以解决效率的问题,即先单独算累计值列表,再插入到原数据集中。但这种写法又不如只需要一句代码的R语言简练。
接着再看计算符合条件的销售员时有什么不同:
R语言在Line 11完成这项计算,主要用了移动行的办法,使用c( 0, addup[- length (addup)])构造了一列新数据。和addup这列相比,新列只是向下移动了一行,去掉了最后一条数据并补上了第一条的0。这样就可以进行比较了:累计值是否小于比较标准? 或者虽然大于比较标准但上一条纪录是否小于比较标准?
R语言不能直接访问相对位置的数据,所以采用了”让相对位置的数据移到当前位置”的办法,虽然效果是一样的,但这个写法不够直观,需要分析者具备较高的逻辑思维能力。
集算器的写法是select(addup<=B3 || (addup>B3 &&addup[-1]<B3))。非常简单清晰!这是集算器特有的相对位置表达方法,即可以用[-1]这种方法表示相对于当前纪录的前1条或后几条纪录。比如A4中的累计值的计算,也可以写成A3.derive(addup[-1]+salesSum:addup)。
和累计值的固定算法不同,这一步算法更自由,集算器的相对位置表达方式比较灵活。
通过上面的例子可以看到,相对位置和行间运算运算可以解决很多看似复杂的问题,集算器在表达相对位置时更灵活,因此在进行复杂问题计算时估计会轻松许多。R语言在整列整行的追加以及固定算法方面写法则更加简练。