聚合组意味着忽略零,除非0是唯一的值

时间:2017-09-01 10:39:26

标签: r dataframe grouping aggregate

给出以下数据格式:

c1 c2 c3
A  B  100  
A  B  200
A  C    0
A  C    0
D  E  550  
D  E  700
D  F  100
D  F    0

我想在同一个A和B的组中得到c3的平均值。使用R的aggregate函数:

aggregate(c3~c1+c2, data=myData, FUN=mean)

我得到了正确的子集均值表:

A  B  150
A  C    0
D  E  625  
D  F   50

然而,如果有值和零,我想排除案例的平均计算。这就是第一个代码的最后两行;

D  F  100
D  F    0

应评估为:

D  F  100

有没有办法修改aggregate功能?或者是否有一种优雅的方式来预先处理我的数据?

3 个答案:

答案 0 :(得分:2)

也许您可以传递一个自定义函数来搜索您提到的条件(x包括零和非零值),如果满足,则返回第一种情况下非零值的平均值,否则您计算标准意味着一如既往。

#prepare data
df <- data.frame(c1=c("A","A","A","A","D","D","D","D"),
           c2= c("B","B","C","C","E","E","F","F"),
           c3= c(100,200,0,0,550,700,100,0))

#aggregate
aggregate(c3~c1+c2, data=df, FUN=(function(x){ifelse(sum(x==0)>0 & sum(x !=0) >0, mean(x[x>0]), mean(x))}))
      c1 c2  c3
    1  A  B 150
    2  A  C   0
    3  D  E 625
    4  D  F 100

答案 1 :(得分:2)

我们可以使用data.table

library(data.table)
setDT(myData)[,  .(c3 = if(!all(c3==0)) mean(c3[c3!=0]) else 0), .(c1, c2)]
#   c1 c2  c3
#1:  A  B 150
#2:  A  C   0
#3:  D  E 625
#4:  D  F 100

答案 2 :(得分:2)

使用aggregate的另一种选择。内部函数通过索引工作,并选择是否将0值转换为NA并使用na.rm=TRUE计算均值或根据所有值是否为0返回0.

aggregate(c3 ~ c1 + c2, dat,
          FUN=function(x) c(mean(x * NA^(!x), na.rm=TRUE), 0)[all(x == 0) + 1L])
  c1 c2  c3
1  A  B 150
2  A  C   0
3  D  E 625
4  D  F 100