使用矩阵值作为索引

Use matrix values as indices

我正在进行 Fisher 排列检验,其中我必须生成治疗状态的所有组合。

我们有 4 名受试者,其中 2 名接受治疗。使用 combn,我可以生成治疗对象的所有组合。例如,第一行表示治疗了第一和第二个受试者。

t(combn(4, 2))

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

如何从这个矩阵转到治疗状态矩阵,如下所示:

      [,1] [,2] [,3] [,4]
[1,]    1    1    0   0
[2,]    1    0    1   0
...

使用 base-R:

res <- t(apply(t(combn(4,2)),MARGIN=1,FUN=function(x){
  return(as.numeric(1:4 %in% x))
}))
> res
     [,1] [,2] [,3] [,4]
[1,]    1    1    0    0
[2,]    1    0    1    0
[3,]    1    0    0    1
[4,]    0    1    1    0
[5,]    0    1    0    1
[6,]    0    0    1    1

怎么样:

out <- matrix(0L, nrow = nrow(x), ncol = max(x))

for (i in 1:nrow(x)) out[i, x[i, ]] <- 1L

> out
     [,1] [,2] [,3] [,4]
[1,]    1    1    0    0
[2,]    1    0    1    0
[3,]    1    0    0    1
[4,]    0    1    1    0
[5,]    0    1    0    1
[6,]    0    0    1    1

我们也可以不使用循环来执行此操作,尽管它的可读性可能会差一些(感谢@Frank 的步法):

m <- matrix(0L, choose(4, 2), 4)
m[cbind(rep(1:choose(4, 2), each = 2), c(combn(4, 2)))] <- 1L

轻松包装到函数中:

participants <- function(m, n){
  if (n > m) stop( )
  mcn <- choose(m, n)
  out <- matrix(0L, mcn, m)
  out[cbind(rep(1:mcn, each = n), c(combn(m, n)))] <- 1L
  out
}

> participants(6, 5)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    1    1    1    1    0
[2,]    1    1    1    1    0    1
[3,]    1    1    1    0    1    1
[4,]    1    1    0    1    1    1
[5,]    1    0    1    1    1    1
[6,]    0    1    1    1    1    1

发表我的评论作为解决方案。这是对@Heroka 的建议的修改。 + 会将 logical 转换为 numeric 并且应该比 as.integer.

更快
+(t(combn(4,2, FUN=function(x) 1:4 %in% x)))
#     [,1] [,2] [,3] [,4]
#[1,]    1    1    0    0
#[2,]    1    0    1    0
#[3,]    1    0    0    1
#[4,]    0    1    1    0
#[5,]    0    1    0    1
#[6,]    0    0    1    1