R 中是否有一种有效的方法将矩阵 M2 的每一行 "paste" 到矩阵 M1 的每一行以获得所有可能的组合?

Is there an efficient way in R to "paste" each row of a matrix M2 onto each row of a matrix M1 to obtain all possible combinations?

假设我有两个矩阵:

M1 <- matrix(letters[1:9], nrow = 3, ncol = 3, byrow = T)
M2 <- matrix(letters[10:18], nrow = 3, ncol = 3, byrow = T)

实际上我有更大的矩阵,有 1000 行。我想要的是在不使用 for 循环的情况下生成以下内容的有效方法,因为这会导致 R 崩溃。

result <- rbind(cbind(M1, matrix(rep(letters[10:12], 3), nrow = 3, ncol = 3, byrow = T)),
                cbind(M1, matrix(rep(letters[13:15], 3), nrow = 3, ncol = 3, byrow = T)),
                cbind(M1, matrix(rep(letters[16:18], 3), nrow = 3, ncol = 3, byrow = T)))

本质上是将 M2 的每一行“粘贴”到 M1 的每一行,这样我就有了所有可能的组合。

您可以使用 expand.gridM1M2 中创建所有可能的行索引组合。

mat <- expand.grid(1:nrow(M1), 1:nrow(M2))
cbind(M1[mat[[1]], ], M2[mat[[2]], ])

#     [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] "a"  "b"  "c"  "j"  "k"  "l" 
# [2,] "d"  "e"  "f"  "j"  "k"  "l" 
# [3,] "g"  "h"  "i"  "j"  "k"  "l" 
# [4,] "a"  "b"  "c"  "m"  "n"  "o" 
# [5,] "d"  "e"  "f"  "m"  "n"  "o" 
# [6,] "g"  "h"  "i"  "m"  "n"  "o" 
# [7,] "a"  "b"  "c"  "p"  "q"  "r" 
# [8,] "d"  "e"  "f"  "p"  "q"  "r" 
# [9,] "g"  "h"  "i"  "p"  "q"  "r" 

您可以尝试 RcppAlgos::permuteGeneral,它比 expand.grid 快得多。

FUN <- function(M1, M2) {
  stopifnot(all.equal(dim(M1), dim(M2)))
  p <- RcppAlgos::permuteGeneral(seq.int(dim(M1)[1]), 2, repetition=T)
  cbind(M1[p[,2],], M2[p[,1],])
}
FUN(M1, M2)
#     [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] "a"  "b"  "c"  "j"  "k"  "l" 
# [2,] "d"  "e"  "f"  "j"  "k"  "l" 
# [3,] "g"  "h"  "i"  "j"  "k"  "l" 
# [4,] "a"  "b"  "c"  "m"  "n"  "o" 
# [5,] "d"  "e"  "f"  "m"  "n"  "o" 
# [6,] "g"  "h"  "i"  "m"  "n"  "o" 
# [7,] "a"  "b"  "c"  "p"  "q"  "r" 
# [8,] "d"  "e"  "f"  "p"  "q"  "r" 
# [9,] "g"  "h"  "i"  "p"  "q"  "r" 

基准

# Unit: microseconds
#        expr     min       lq      mean   median      uq       max neval cld
# expand.grid 147.724 151.4235 628.38420 154.8680 157.291 46840.374   100   a
#   RcppAlgos  74.500  77.4340  84.75624  80.1125  82.409   238.807   100   a