1) apply/tapply 对于每一行,使用名称前缀的 INDEX 和函数 mean 在其上使用 tapply。转置结果。没有使用任何包。
prefix <- sub("\\..*", "", names(df))
t(apply(df, 1, tapply, prefix, mean))
给出这个矩阵(如果您需要数据框结果,请将其包装在 data.frame(...) 中):
CB_1 HC_1 HC_2
[1,] 0.5 1.5 3
[2,] 5.0 1.5 3
[3,] 4.5 2.0 4
[4,] 4.0 5.0 5
2) lm 运行指定的回归。公式中的 +0 表示不添加截距。系数的转置将是所需的矩阵m。在下一行使名称更好。 prefix 来自 (1)。没有使用任何包。
m <- t(coef(lm(t(df) ~ prefix + 0)))
colnames(m) <- sub("prefix", "", colnames(m))
m
给出这个矩阵
CB_1 HC_1 HC_2
[1,] 0.5 1.5 3
[2,] 5.0 1.5 3
[3,] 4.5 2.0 4
[4,] 4.0 5.0 5
这源于以下事实:(1) 模型矩阵 X 仅包含 1 和 0,并且 (2) 它的不同列是正交的。模型矩阵如下所示:
X <- model.matrix(~ prefix + 0) # model matrix
X
给予:
prefixCB_1 prefixHC_1 prefixHC_2
1 1 0 0
2 1 0 0
3 0 0 1
4 0 1 0
5 0 1 0
attr(,"assign")
[1] 1 1 1
attr(,"contrasts")
attr(,"contrasts")$prefix
[1] "contr.treatment"
因为模型矩阵X 的列是正交的,所以df(t(df) 的列)的特定行 y 的任何列对应的系数只是 sum(x * y) / sum(x * x),并且由于 x 是一个 0/1 向量,等于 y 的值的平均值,对应于 x 中的 1。
3) stack/tapply 转换为长格式,同时插入id 列。然后使用tapply 转换回宽格式tapply-ing mean。没有使用任何包。
long <- transform(stack(df), ind = sub("\\..*", "", ind), id = c(row(df)))
with(long, tapply(values, long[c("id", "ind")], mean))
给这张桌子。如果你想要一个data.frame,把它包装在as.data.frame.matrix中。
ind
id CB_1 HC_1 HC_2
1 0.5 1.5 3
2 5.0 1.5 3
3 4.5 2.0 4
4 4.0 5.0 5