快速生成矩阵的笛卡尔积

8
假设我有一个包含10行和2列的矩阵x。我想生成一个新的矩阵M,其中包含x中每个唯一的行对 - 也就是说,一个新的矩阵,它有55行和4列。
例如,
x <- matrix (nrow=10, ncol=2, 1:20)

M <- data.frame(matrix(ncol=4, nrow=55))
k <- 1
for (i in 1:nrow(x))
for (j in i:nrow(x))
{
    M[k,] <- unlist(cbind (x[i,], x[j,]))
    k <- k + 1
}

所以,x 是:
      [,1] [,2]
 [1,]    1   11
 [2,]    2   12
 [3,]    3   13
 [4,]    4   14
 [5,]    5   15
 [6,]    6   16
 [7,]    7   17
 [8,]    8   18
 [9,]    9   19
[10,]   10   20

接着M有4列,前两列是来自x的一行,后两列是来自x的另一行:

> head(M,10)
   X1 X2 X3 X4
1   1 11  1 11
2   1 11  2 12
3   1 11  3 13
4   1 11  4 14
5   1 11  5 15
6   1 11  6 16
7   1 11  7 17
8   1 11  8 18
9   1 11  9 19
10  1 11 10 20

在R中,有没有更快或更简单(或两者兼备)的方法来做这件事?
5个回答

9

expand.grid()函数在这方面非常有用:

R> GG <- expand.grid(1:10,1:10)
R> GG <- GG[GG[,1]>=GG[,2],]     # trim it to your 55 pairs
R> dim(GG)
[1] 55  2
R> head(GG)
  Var1 Var2
1    1    1
2    2    1
3    3    1
4    4    1
5    5    1
6    6    1
R> 

现在,您有了“n *(n + 1)/ 2”个子集,您可以简单地索引您的原始矩阵。

3

我不太明白你在做什么,所以我会提出一些可能有用的建议。

这是我认为两列的笛卡尔积:

expand.grid(x[,1],x[,2])

以前从没听说过expand.grid()。Dirk的回答把所有东西都搞清楚了(像往常一样...)。 - Josh Reich

2
您也可以尝试使用“relations”包。这里是说明文档链接:点击此处。使用方法如下:
relation_table(x %><% x)

1

使用Dirk的答案:

idx <- expand.grid(1:nrow(x), 1:nrow(x))
idx<-idx[idx[,1] >= idx[,2],]
N <- cbind(x[idx[,2],], x[idx[,1],])

> all(M == N)
[1] TRUE

谢谢大家!


1

受到其他答案的启发,这里有一个函数实现了两个矩阵的笛卡尔积,在两个矩阵的情况下,是完整的笛卡尔积,对于只有一个参数的情况,则省略每对中的一个:

cartesian_prod <- function(M1, M2) {
if(missing(M2)) {  M2 <- M1
     ind  <- expand.grid(1:NROW(M1), 1:NROW(M2))
     ind <- ind[ind[,1] >= ind[,2],] } else {
                                          ind  <- expand.grid(1:NROW(M1), 1:NROW(M2))}
rbind(cbind(M1[ind[,1],], M2[ind[,2],]))

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接