3 votes

Comment lier toutes les combinaisons de lignes d'une liste de matrices en R

J'ai une liste de matrices. La longueur de cette liste est inconnue (bien que pour mon exemple j'utilise une liste de 3 matrices 2x2).

[[1]]
     [,1] [,2]
[1,]    1    1
[2,]    2    2

[[2]]
     [,1] [,2]
[1,]    3    3
[2,]    4    4

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

À partir de cette liste, j'aimerais générer une matrice de toutes les combinaisons possibles des lignes de chaque matrice de la liste. En d'autres termes, je souhaite obtenir cette matrice en sortie :

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

J'ai regardé d'autres exemples (par exemple, j'aimerais beaucoup utiliser expand.grid) mais tous ont tendance à développer des combinaisons d'éléments des lignes ou à appliquer une autre fonction que je n'ai pas pu adapter.

De plus, il doit fonctionner sur une liste de matrices de n'importe quelle taille.

J'ai une solution mais je suis sûr qu'il doit y en avoir une meilleure / plus courte / plus élégante / plus rapide qui se cache quelque part. Pouvez-vous m'aider à la trouver ?

Voici mon code :

# New matrix will be stored in here.
# Don't like but is there a better way?
m.combs <- c()

expand.grid.2 <- function(lst) {

  if (is.null(m.combs)) {

    m.combs <<- lst

  } else {

    m.current <- m.combs
    n <- nrow(m.combs)

    for (i in 1:nrow(lst)) {

      if(i == 1)  # for first iteration cbind new matrix
        m.combs <<- cbind(m.combs, matrix(rep(lst[i, ], each = n), nrow = n))
      else        # for next iterations rbind new matrix
        m.combs <<- rbind(m.combs, cbind(m.current, matrix(rep(lst[i, ], each = n), nrow = n)))
    }
  }
}

m1 <- matrix(c(1,1,2,2), nrow = 2, ncol = 2, byrow = TRUE)
m2 <- matrix(c(3,3,4,4), nrow = 2, ncol = 2, byrow = TRUE)
m3 <- matrix(c(5,5,6,6), nrow = 2, ncol = 2, byrow = TRUE)
lst <- list(m1, m2, m3)

rapply(lst, expand.grid.2)
print(m.combs)

4voto

Joris Chau Points 1728

Voici une approche possible :

## get indices of all row combinations
m.combs <- expand.grid(lapply(l, function(x) seq_len(nrow(x))))

## extract rows and combine into matrix
do.call(cbind, Map(function(x, y) x[y, ], l, m.combs))
#>      [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,]    1    1    3    3    5    5
#> [2,]    2    2    3    3    5    5
#> [3,]    1    1    4    4    5    5
#> [4,]    2    2    4    4    5    5
#> [5,]    1    1    3    3    6    6
#> [6,]    2    2    3    3    6    6
#> [7,]    1    1    4    4    6    6
#> [8,]    2    2    4    4    6    6

Première utilisation expand.grid pour obtenir les indices de ligne (par élément de liste) correspondant à toutes les combinaisons que nous souhaitons générer. Ensuite, il faut extraire les lignes correspondantes et les combiner en une seule matrice.

Données

mat <- matrix(rep(1:6, 2), ncol = 2)
l <- list(mat[1:2, ], mat[3:4, ], mat[5:6, ])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X