2013-01-23 35 views
6

说我下表DataTable具有不同功能的聚合多个变量

Cat1 | Cat2 | Val1 | Val2 
-------------------------------------------- 
A  | A  | 1  | 2 
A  | B  | 3  | 4 
B  | A  | 5  | 6 
B  | B  | 7  | 8 
A  | A  | 2  | 4 
A  | B  | 6  | 8 
B  | A  | 10  | 12 
B  | B  | 14  | 16 

这一点我希望通过CAT1和CAT2聚集,以分别VAL1和VAL2的总和和平均过,我怎么可能达致这?

Cat1 | Cat2 | Sum Val1 | Avg Val2 
-------------------------------------------- 
A  | A  | 3  | 3 
A  | B  | 9  | 6 
B  | A  | 15  | 9 
B  | B  | 21  | 12 

我已经取得了单变量聚合,聚合函数:

aggregate(
     Val1 
    ~ Cat1 + Cat2 
    data=DataTable, 
    FUNC=sum 
) 

但尽管有cbind玩耍,不能得到我想要的行为。我24小时学习R,所以我对这些概念不够熟悉,不能完全理解我一直在做什么(总是很危险!),但是认为这一点很容易实现。 |

+1

这是这个主题的重复:https://stackoverflow.com/questions/12064202/using-aggregate-to -apply-several-functions-on-several-variables-in-One-call –

回答

11
set.seed(45) 
df <- data.frame(c1=rep(c("A","A","B","B"), 2), 
       c2 = rep(c("A","B"), 4), 
       v1 = sample(8), 
       v2 = sample(1:100, 8)) 
> df 
# c1 c2 v1 v2 
# 1 A A 6 19 
# 2 A B 3 1 
# 3 B A 2 37 
# 4 B B 8 86 
# 5 A A 5 30 
# 6 A B 1 44 
# 7 B A 7 41 
# 8 B B 4 39 

v1 <- aggregate(v1 ~ c1 + c2, data = df, sum) 
v2 <- aggregate(v2 ~ c1 + c2, data = df, mean) 
out <- merge(v1, v2, by=c("c1","c2")) 
> out 
# c1 c2 v1 v2 
# 1 A A 11 24.5 
# 2 A B 4 22.5 
# 3 B A 9 39.0 
# 4 B B 12 62.5 

**Edit:**我会建议你使用data.table,因为它使事情变得非常简单:

require(data.table) 
dt <- data.table(df) 
dt.out <- dt[, list(s.v1=sum(v1), m.v2=mean(v2)), 
        by=c("c1","c2")] 
> dt.out 

# c1 c2 s.v1 m.v2 
# 1: A A 11 24.5 
# 2: A B 4 22.5 
# 3: B A 9 39.0 
# 4: B B 12 62.5 
+1

我认为'data.table'是要走的路,但是它好像OP不希望'sum' *和*'的意思是'为每个变量(如果你想更新你的答案)。 – A5C1D2H2I1M1N2O1R2T1

7

这里有一个基础R解决方案:

首先,你的数据:

x <- structure(list(Cat1 = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 
2L), .Label = c("A", "B"), class = "factor"), Cat2 = structure(c(1L, 
2L, 1L, 2L, 1L, 2L, 1L, 2L), .Label = c("A", "B"), class = "factor"), 
    Val1 = c(1L, 3L, 5L, 7L, 2L, 6L, 10L, 14L), Val2 = c(2L, 
    4L, 6L, 8L, 4L, 8L, 12L, 16L)), .Names = c("Cat1", "Cat2", 
"Val1", "Val2"), class = "data.frame", row.names = c(NA, -8L)) 

然后,使用ave()unique()机智hin within()

unique(
    within(x, { 
    sum_val1 <- ave(Val1, Cat1, Cat2, FUN = sum) 
    mean_val2 <- ave(Val2, Cat1, Cat2, FUN = mean) 
    rm(Val1, Val2) 
    }) 
) 
# Cat1 Cat2 mean_val2 sum_val1 
# 1 A A   3  3 
# 2 A B   6  9 
# 3 B A   9  15 
# 4 B B  12  21 

或者,如果您熟悉SQL,使用sqldf

library(sqldf) 
sqldf("select Cat1, Cat2, 
     sum(Val1) `Sum_Val1`, 
     avg(Val2) `Avg_Val2` 
     from x group by Cat1, Cat2") 
+0

感谢您的选择。我喜欢另一个海报提供的选项,因为它感觉更多一点R。使用data.table的熟悉性虽然很吸引人。我注意到使用avg函数。 R语言中的函数(例如中位数)可以从sql语法中调用吗? – user524261

+2

@ user524261,不知道'data.table'比'ave'多R,但这很酷。至于你关于在SQL中调用R函数的问题:不,你必须使用适当的SQL命令(例如,在这里我们称之为'avg'而不是'mean')和诸如“median”之类的东西(据我所知)不能直接使用SQL,但可以使用“order by”,“length”和其他熟悉的命令来确定。 – A5C1D2H2I1M1N2O1R2T1