2016-05-23 66 views
0

我想获取data.table中某个列的值的总值和净值之和。通过整笔款项,我的意思是忽略负值,因此,对于在这个例子中a,净总和是4,总金额为5从data.table中的列中获取总数和净总数R

>dt = data.table(id = c("a","a","a","b","b","b","b","c","c"),value = c(-1,2,3,-3,4,-2,3,-1,1)) 
>head(dt,3) 
    id value 
1: a -1 
2: a  2 
3: a  3 

我可以通过添加一个额外的列,这样做:

>dt$grossValue = dt$value 
>dt$grossValue[dt$grossValue < 0] = 0 
>dt[,.(netTotal = sum(value),grossTotal= sum(grossValue)),by=id] 
    id netTotal grossTotal 
1: a  4   5 
2: b  2   7 
3: c  0   1 

但我真的不希望有一个额外的列添加到数据,因为有几百万行的,我可能要跨越多个列做到这一点。有没有办法直接做到这一点?我可以计算出如何得到总的总数或净总数(通过在i中加上value > 0得到总的总数),但是不能同时得到总数。

回答

4

这是你在找什么?

dt[, .(netTotal = sum(value), grossTotal = sum(value * (value > 0))), by=id] 

我一次计算两列。使用(value > 0)作为逻辑删除sum中的负值。

+0

是的,这也正是它。对R相对缺乏经验,并且不熟悉这个习语。谢谢。 –

0

您是否熟悉dplyr软件包?如果没有,请检查一下,一旦你掌握了这些任务,这些任务就会变得非常简单。

library(dplyr) 
dt %>% group_by(id) %>% summarize(net = sum(value), gross = sum(ifelse(value > 0, value, 0))) 
1

我显然误解了这个请求,因为我还以为你也要求总计。因此,这里的是无偿的解决方案:

rbind(dt[,.(netTotal = sum(value),grossTotal= sum(value*(value>0))),by=id], 
data.table(id="all", netTotal=dt[,sum(value)], grossTotal=dt[,sum(value*(value>0))])) 
#------------- 
    id netTotal grossTotal 
1: a  4   5 
2: b  2   7 
3: c  0   1 
4: all  6   13 
0

我们也可以子集,而不是通过逻辑指数乘以

dt[, .(netTotal = sum(value), grossTotal = sum(value[value>0])) , id] 
# id netTotal grossTotal 
#1: a  4   5 
#2: b  2   7 
#3: c  0   1