web-dev-qa-db-fra.com

Générer une liste de toutes les combinaisons possibles d'éléments de vecteur

J'essaie de générer toutes les combinaisons possibles de 0 et de 1 dans un vecteur de longueur 14. Existe-t-il un moyen facile d'obtenir cette sortie sous forme de liste de vecteurs, ou mieux encore, une trame de données?

Pour mieux démontrer ce que je recherche, supposons que je ne veux qu'un vecteur de longueur 3. Je voudrais pouvoir générer ce qui suit:

 (1,1,1), (0,0,0), (1,1,0), (1,0,0), (1,0,1), (0,1,0), (0,1,1), (0,0,0)

Toute aide serait appréciée!

Merci,

42
Mayou

Vous cherchez expand.grid.

expand.grid(0:1, 0:1, 0:1)

Ou, pour le cas long:

n <- 14
l <- rep(list(0:1), n)

expand.grid(l)
74
Justin

Comme alternative à l'approche de @ Justin, vous pouvez également utiliser CJ à partir du package "data.table". Ici, j'ai également utilisé replicate pour créer ma liste de 14 zéros et uns.

library(data.table)
do.call(CJ, replicate(14, 0:1, FALSE))
#        V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
#     1:  0  0  0  0  0  0  0  0  0   0   0   0   0   0
#     2:  0  0  0  0  0  0  0  0  0   0   0   0   0   1
#     3:  0  0  0  0  0  0  0  0  0   0   0   0   1   0
#     4:  0  0  0  0  0  0  0  0  0   0   0   0   1   1
#     5:  0  0  0  0  0  0  0  0  0   0   0   1   0   0
#    ---                                               
# 16380:  1  1  1  1  1  1  1  1  1   1   1   0   1   1
# 16381:  1  1  1  1  1  1  1  1  1   1   1   1   0   0
# 16382:  1  1  1  1  1  1  1  1  1   1   1   1   0   1
# 16383:  1  1  1  1  1  1  1  1  1   1   1   1   1   0
# 16384:  1  1  1  1  1  1  1  1  1   1   1   1   1   1
6

Il y a 16384 permutations possibles. Vous pouvez utiliser le package iterpc pour récupérer le résultat de manière itérative.

library(iterpc)
I = iterpc(2, 14, label=c(0,1), order=T, replace=T)
getnext(I)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0
getnext(I)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 1
getnext(I)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 1 0

Si vous voulez tous les résultats, vous pouvez toujours utiliser getall(I).

5
Randy Lai

tidyr a quelques options similaires à expand.grid().

tidyr::crossing() renvoie un tibble et ne convertit pas les chaînes en facteurs (bien que vous puissiez faire expand.grid(..., stringsAsFactors = F)).

library(tidyr)

crossing(var1 = 0:1, var2 = 0:1, var3 = 0:1)
# A tibble: 8 x 3
   var1  var2  var3
  <int> <int> <int>
1     0     0     0
2     0     0     1
3     0     1     0
4     0     1     1
5     1     0     0
6     1     0     1
7     1     1     0
8     1     1     1

tidyr::expand() peut donner les deux combinaisons de seules valeurs qui apparaissent dans les données, comme ceci:

expand(mtcars, nesting(vs, cyl))
# A tibble: 5 x 2
     vs   cyl
  <dbl> <dbl>
1     0     4
2     0     6
3     0     8
4     1     4
5     1     6

ou toutes les combinaisons possibles de deux variables, même s'il n'y a pas d'observation avec ces valeurs spécifiques dans les données dans les données, comme ceci:

expand(mtcars, vs, col)
# A tibble: 6 x 2
     vs   cyl
  <dbl> <dbl>
1     0     4
2     0     6
3     0     8
4     1     4
5     1     6
6     1     8

(Vous pouvez voir qu'il n'y avait aucune observation dans les données d'origine où vs == 1 & cyl == 8)

tidyr::complete() peut également être utilisé de la même façon que expand.grid(). Ceci est un exemple de la documentation:

df <- dplyr::tibble(
  group = c(1:2, 1),
  item_id = c(1:2, 2),
  item_name = c("a", "b", "b"),
  value1 = 1:3,
  value2 = 4:6
)
df %>% complete(group, nesting(item_id, item_name))

# A tibble: 4 x 5
  group item_id item_name value1 value2
  <dbl>   <dbl> <chr>      <int>  <int>
1     1       1 a              1      4
2     1       2 b              3      6
3     2       1 a             NA     NA
4     2       2 b              2      5

Cela donne toutes les combinaisons possibles de item_id et item_name pour chaque groupe - cela crée une ligne pour le groupe 2 item_id 1 et item_name a.

5
sbha

Puisque vous avez affaire à des 0 et des 1, il semble naturel de penser aux entiers en termes de bits. En utilisant une fonction qui a été légèrement modifiée par rapport à cela post (MyIntToBit ci-dessous), avec votre choix de fonctions apply, nous pouvons obtenir le résultat souhaité.

MyIntToBit <- function(x, Dig) {
    i <- 0L
    string <- numeric(Dig)
    while (x > 0) {
        string[Dig - i] <- x %% 2L
        x <- x %/% 2L
        i <- i + 1L
    }
    string
}

Si vous voulez une liste, utilisez lapply comme ceci:

lapply(0:(2^14 - 1), function(x) MyIntToBit(x,14))

Si vous préférez une matrice, sapply fera l'affaire:

sapply(0:(2^14 - 1), function(x) MyIntToBit(x,14))

Voici des exemples de sorties:

> lapply(0:(2^3 - 1), function(x) MyIntToBit(x,3))
[[1]]
[1] 0 0 0

[[2]]
[1] 0 0 1

[[3]]
[1] 0 1 0

[[4]]
[1] 0 1 1

[[5]]
[1] 1 0 0

[[6]]
[1] 1 0 1

[[7]]
[1] 1 1 0

[[8]]
[1] 1 1 1


> sapply(0:(2^3 - 1), function(x) MyIntToBit(x,3))
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    0    0    0    1    1    1    1
[2,]    0    0    1    1    0    0    1    1
[3,]    0    1    0    1    0    1    0    1 
3
Joseph Wood

Il s'agit d'une approche différente des réponses précédentes. Si vous avez besoin de toutes les combinaisons possibles de 14 valeurs de 1 et 0, c'est comme générer tous les nombres possibles de 0 à (2 ^ 14) -1 et en conserver la représentation binaire.

n <- 14
lapply(0:(2^n-1), FUN=function(x) head(as.integer(intToBits(x)),n))
1
Patricio Moracho