我有一个包含列名的矩阵,显示分组信息(在下面的示例中为组a和组B)。我想要的是,对于每一行,计算一个给定的汇总统计数据,比如使用属于每个组的列的平均值。下面是一个示例代码:
#input data
data = matrix(1:100, 10, 10, byrow = T)
colnames(data) = rep(c("A", "B"), each = 5)
data
#calculation
result = t(apply(data, 1, function(x, label){aggregate(x, by=list(label), FUN=mean)$x}, label = colnames(data)))
result
有不同的方法可以做到这一点(比如for循环或像上面的实现一样使用apply)。然而,当我在具有数百行和至少10k列的矩阵上使用它时,这种实现不是很有效。我想知道是否有任何更快,更有效的方式来实现这一点?我的输入数据格式是矩阵,所以任何基于其他数据类型实现的方法都需要考虑数据类型转换的时间。
这是使用tapply
的最佳场景:
tapply(t(data), list(col(data), array(colnames(data), dim(t(data)))), mean)
A B
1 3 8
2 13 18
3 23 28
4 33 38
5 43 48
6 53 58
7 63 68
8 73 78
9 83 88
10 93 98
tapply(data, list(t(colnames(data))[rep(1,nrow(data)), ], row(data)), mean)
1 2 3 4 5 6 7 8 9 10
A 3 13 23 33 43 53 63 73 83 93
B 8 18 28 38 48 58 68 78 88 98
tapply(t(data), interaction(colnames(data), col(data)), mean)
A.1 B.1 A.2 B.2 A.3 B.3 A.4 B.4 A.5 B.5 A.6 B.6 A.7 B.7 A.8 B.8 A.9 B.9 A.10 B.10
3 8 13 18 23 28 33 38 43 48 53 58 63 68 73 78 83 88 93 98
更多基本R解:
sapply(split.default(data.frame(data), colnames(data)), rowMeans)
A B
[1,] 3 8
[2,] 13 18
[3,] 23 28
[4,] 33 38
[5,] 43 48
[6,] 53 58
[7,] 63 68
[8,] 73 78
[9,] 83 88
[10,] 93 98
data.frame(data) |>
reshape(split(1:ncol(data), colnames(data)), dir = 'long') |>
((x)aggregate(.~id, x, mean))()
id time A B
1 1 3 3 8
2 2 3 13 18
3 3 3 23 28
4 4 3 33 38
5 5 3 43 48
6 6 3 53 58
7 7 3 63 68
8 8 3 73 78
9 9 3 83 88
10 10 3 93 98
我们可以在base R
中使用aggregate
aggregate(Freq ~ ., as.data.frame.table(data), FUN = mean)
或者遍历unique
列名,对数据进行子集并获得rowMeans
sapply(unique(colnames(data)), function(nm)
rowMeans(data[, colnames(data) == nm]))
或者用collapse
代替dapply
library(collapse)
dapply(data, MARGIN = 1, FUN = function(x) fmean(x, g = colnames(data)))
A B
[1,] 3 8
[2,] 13 18
[3,] 23 28
[4,] 33 38
[5,] 43 48
[6,] 53 58
[7,] 63 68
[8,] 73 78
[9,] 83 88
[10,] 93 98