如何使用R进行多个单独组的相同字段聚合

时间:2014-04-30 12:38:58

标签: r aggregate apply

我试图分别对几个(实际上是几百个)组进行指标计数(不是所有组的所有组合)。我将通过简化示例演示它:

假设我有该数据集

data<-cbind(c(1,1,1,2,2,2)
,c(1,1,2,2,2,3)
,c(3,2,1,2,2,3))
> data

      [,1] [,2] [,3]
[1,]    1    1    3
[2,]    1    1    2
[3,]    1    2    1
[4,]    2    2    2
[5,]    2    2    2
[6,]    2    3    3

和指标

some_indicator<-c(1,0,0,1,0,1)

然后我想运行没有循环(比如像列应用),比如

aggregate(some_indicator,list(data[,1]),sum)
aggregate(some_indicator,list(data[,2]),sum)
aggregate(some_indicator,list(data[,3]),sum)

将产生以下结果:

     [,1] [,2] [,3]
[1,]    1    1    0
[2,]    2    1    1
[3,]    0    1    2

即。对于每列(值子集在列之间不会发生太大变化),按值计算指标并合并它。

目前我用循环列编写了它,但我需要更有效的方法,因为有很多列而且需要一个多小时。

提前致谢, 迈克尔。

2 个答案:

答案 0 :(得分:4)

1)tapply tapply的第一个参数是data,每列都被some_indicator替换。第二个参数表明我们希望按数据组和列号分组。

result <- tapply(replace(data, TRUE, some_indicator), list(data, col(data)), sum)
replace(unname(result), is.na(result), 0)

对于问题中显示的输入,最后一行给出:

     [,1] [,2] [,3]
[1,]    1    1    0
[2,]    2    1    1
[3,]    0    1    2

1a)tapply 稍微长一点的tapply解决方案如下。 fun以列为参数,并使用tapplysome_indicator中的组与该列作为组进行求和;但是,不同的列可以在其中具有不同的组,以确保它们都具有相同的组(为了以后的对齐),我们实际按factor(x, levs)分组。 sapplyfun应用于data的每一列。需要as.data.frame,因为data是一个矩阵,因此sapply将应用于每个元素,而不是每个列,如果我们将其应用于此。

 levs <- levels(factor(data))
 fun <- function(x) tapply(some_indicator, factor(x, levs), sum)
 result <- sapply(as.data.frame(data), fun)
 replace(unname(result), is.na(result), 0)

2)xtabs 这与tapply解决方案非常相似。它确实具有以下优点:(1)sum暗示xtabs因此无需指定,并且(2)未填充的单元格填充0而不是NA,从而消除了替换的额外步骤NAs为0.另一方面,我们必须使用c将公式的每个组成部分解释为一个向量,因为与tapply不同,xtabs公式将不接受矩阵:

result <- xtabs(c(replace(data, TRUE, some_indicator)) ~ c(data) + c(col(data)))
dimnames(result) <- NULL

对于问题中的数据,这给出了:

> result
     [,1] [,2] [,3]
[1,]    1    1    0
[2,]    2    1    1
[3,]    0    1    2

已修订已修订tapply解决方案,并添加了xtabs解决方案。

答案 1 :(得分:1)

melt来自&#34; reshape2&#34;有一种矩阵的方法,这在这里很有用。使用&#34; reshape2&#34;,解决方案可以像以下一样简单:

library(reshape2)
dcast(cbind(some_indicator, melt(data)), 
      value ~ Var2, value.var= "some_indicator", 
      fun.aggregate=sum)
#   value 1 2 3
# 1     1 1 1 0
# 2     2 2 1 1
# 3     3 0 1 2

此答案假定您对melt的{​​{1}}工作原理有一些先验知识,特别是它会创建一个三列matrix,其中包含&#34; Var1&#34;表示data.frame(或数字),&#34; Var2&#34;表示rownames(或数字)和&#34;值&#34;表示colnames

中的值