Generando todas las permutaciones distintas de una lista en R

Estoy intentando crear una lista de permutaciones de una lista, por ejemplo, perms(list("a", "b", "c")) devuelve

 list(list("a", "b", "c"), list("a", "c", "b"), list("b", "a", "c"), list("b", "c", "a"), list("c", "a", "b"), list("c", "b", "a")) 

No estoy seguro de cómo proceder, cualquier ayuda sería muy apreciada.

combinat::permn hará ese trabajo:

 > library(combinat) > permn(letters[1:3]) [[1]] [1] "a" "b" "c" [[2]] [1] "a" "c" "b" [[3]] [1] "c" "a" "b" [[4]] [1] "c" "b" "a" [[5]] [1] "b" "c" "a" [[6]] [1] "b" "a" "c" 

Tenga en cuenta que el cálculo es enorme si el elemento es grande.

Hace un tiempo tuve que hacer esto en la base R sin cargar ningún paquete.

 permutations < - function(n){ if(n==1){ return(matrix(1)) } else { sp <- permutations(n-1) p <- nrow(sp) A <- matrix(nrow=n*p,ncol=n) for(i in 1:n){ A[(i-1)*p+1:p,] <- cbind(i,sp+(sp>=i)) } return(A) } } 

Uso:

 > matrix(letters[permutations(3)],ncol=3) [,1] [,2] [,3] [1,] "a" "b" "c" [2,] "a" "c" "b" [3,] "b" "a" "c" [4,] "b" "c" "a" [5,] "c" "a" "b" [6,] "c" "b" "a" 

Puedes probar las permutations() del paquete gtools , pero a diferencia de permn() de combinat , no permn() una lista:

 > library(gtools) > permutations(3, 3, letters[1:3]) [,1] [,2] [,3] [1,] "a" "b" "c" [2,] "a" "c" "b" [3,] "b" "a" "c" [4,] "b" "c" "a" [5,] "c" "a" "b" [6,] "c" "b" "a" 

la base R también puede proporcionar la respuesta:

 all < - expand.grid(p1 = letters[1:3], p2 = letters[1:3], p3 = letters[1:3], stringsAsFactors = FALSE) perms <- all[apply(all, 1, function(x) {length(unique(x)) == 3}),] 
 # Another recursive implementation # for those who like to roll their own, no package required permutations < - function( x, prefix = c() ) { if(length(x) == 0 ) return(prefix) do.call(rbind, sapply(1:length(x), FUN = function(idx) permutations( x[-idx], c( prefix, x[idx])), simplify = FALSE)) } permutations(letters[1:3]) # [,1] [,2] [,3] #[1,] "a" "b" "c" #[2,] "a" "c" "b" #[3,] "b" "a" "c" #[4,] "b" "c" "a" #[5,] "c" "a" "b" #[6,] "c" "b" "a" 

Una solución en la base R, sin dependencias en otros paquetes:

 > getPerms < - function(x) { if (length(x) == 1) { return(x) } else { res <- matrix(nrow = 0, ncol = length(x)) for (i in seq_along(x)) { res <- rbind(res, cbind(x[i], Recall(x[-i]))) } return(res) } } > getPerms(letters[1:3]) [,1] [,2] [,3] [1,] "a" "b" "c" [2,] "a" "c" "b" [3,] "b" "a" "c" [4,] "b" "c" "a" [5,] "c" "a" "b" [6,] "c" "b" "a" 

Espero que esto ayude.

Tratar:

 > a = letters[1:3] > eg = expand.grid(a,a,a) > eg[!(eg$Var1==eg$Var2 | eg$Var2==eg$Var3 | eg$Var1==eg$Var3),] Var1 Var2 Var3 6 cba 8 bca 12 cab 16 acb 20 bac 22 abc 

Según lo sugerido por @Adrian en los comentarios, la última línea se puede reemplazar por:

 eg[apply(eg, 1, anyDuplicated) == 0, ] 

Una solución divertida “probabilística” que utiliza una muestra para la base R:

 elements < - c("a", "b", "c") k <- length(elements) res=unique(t(sapply(1:200, function(x) sample(elements, k)))) # below, check you have all the permutations you need (if not, try again) nrow(res) == factorial(k) res 

Básicamente llama a muchas muestras aleatorias, esperando obtenerlas todas, y las hace únicas.

Qué pasa

 pmsa < - function(l) { pms <- function(n) if(n==1) return(list(1)) else unlist(lapply(pms(n-1),function(v) lapply(0:(n-1),function(k) append(v,n,k))),recursive = F) lapply(pms(length(l)),function(.) l[.]) } 

Esto da una lista. Entonces

pmsa(letters[1:3])