聚合具有不同功能的多个变量

问题描述 投票:0回答:2

假设我有下表

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,所以我对这些概念还不够熟悉,无法完全理解我一直在做的事情(总是很危险!),但我认为这一定很容易实现。 |

r aggregate
2个回答
13
投票
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

9
投票

这是一个基本的 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()
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")
© www.soinside.com 2019 - 2024. All rights reserved.