我正在尝试分别对几个(实际上是数百个)组执行指标计数(不对所有组的所有组合进行计数)。我将通过简化示例进行演示:
假设我有那个数据集
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
即对于每列(值子集在列之间变化不大),请按值计算指标并将其合并。
目前,我使用循环遍历列来编写它,但是我需要一种更有效的方法,因为有很多列并且需要一个多小时。
提前致谢,
迈克尔
最佳答案
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
解决方案。 fun
使用一列作为其参数,并使用tapply
将该列作为组对some_indicator
中的组求和;但是,不同的列中可以有不同的组集,因此要确保它们都具有相同的组集(以供以后对齐),我们实际上是按factor(x, levs)
进行分组的。 sapply
将fun
应用于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,从而省去了用0替换NA的额外步骤。另一方面,我们必须使用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
解决方案。