Быстро сгенерируйте декартово произведение матрицы
Вопрос
Допустим, у меня есть матрица x
который содержит 10 строк и 2 столбца.Я хочу создать новую матрицу 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
и следующие 2 – это еще одна строка из 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?
Решение
А 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», и вы можете просто индексировать исходную матрицу.
Другие советы
Я не совсем понимаю, что вы делаете, поэтому просто выброшу что-нибудь, что может помочь, а может и не помочь.
Вот что я считаю декартовым произведением двух столбцов:
expand.grid(x[,1],x[,2])
Вы также можете попробовать пакет «отношения». Вот виньетка. Это должно работать следующим образом:
relation_table(x %><% x)
Используя ответ Дирка:
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
Всем спасибо!
Вдохновленный другими ответами, вот функция, реализующая декартово произведение двух матриц, в случае двух матриц - полное декартово произведение только для одного аргумента, опуская один из каждой пары:
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],]))
}