2013-01-23 33 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