Combinaison unique de tous les éléments de deux (ou plus) vecteurs

95

J'essaie de créer une combinaison unique de tous les éléments à partir de deux vecteurs de taille différente dans R.

Par exemple, le premier vecteur est

a <- c("ABC", "DEF", "GHI")

et le second est les dates stockées sous forme de chaînes actuellement

b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

J'ai besoin de créer un bloc de données avec deux colonnes comme celui-ci

> data
    a          b
1  ABC 2012-05-01
2  ABC 2012-05-02
3  ABC 2012-05-03
4  ABC 2012-05-04
5  ABC 2012-05-05
6  DEF 2012-05-01
7  DEF 2012-05-02
8  DEF 2012-05-03
9  DEF 2012-05-04
10 DEF 2012-05-05
11 GHI 2012-05-01
12 GHI 2012-05-02
13 GHI 2012-05-03
14 GHI 2012-05-04
15 GHI 2012-05-05

Donc, fondamentalement, je recherche une combinaison unique en considérant tous les éléments d'un vecteur (a) juxtaposés à tous les éléments du deuxième vecteur (b).

Une solution idéale se généraliserait à plus de vecteurs d'entrée.


Voir aussi:
Comment générer une matrice de combinaisons

Godel
la source

Réponses:

139

c'est peut-être ce que tu cherches

> expand.grid(a,b)
   Var1       Var2
1   ABC 2012-05-01
2   DEF 2012-05-01
3   GHI 2012-05-01
4   ABC 2012-05-02
5   DEF 2012-05-02
6   GHI 2012-05-02
7   ABC 2012-05-03
8   DEF 2012-05-03
9   GHI 2012-05-03
10  ABC 2012-05-04
11  DEF 2012-05-04
12  GHI 2012-05-04
13  ABC 2012-05-05
14  DEF 2012-05-05
15  GHI 2012-05-05

Si l'ordre qui en résulte n'est pas ce que vous voulez, vous pouvez trier par la suite. Si vous nommez les arguments à expand.grid, ils deviendront des noms de colonnes:

df = expand.grid(a = a, b = b)
df[order(df$a), ]

Et se expand.gridgénéralise à n'importe quel nombre de colonnes d'entrée.

shhhhimhuntingrabbits
la source
4
Et sans avoir besoin plyrde faire un tri:result <- expand.grid(a=a,b=b); result <- result[order(result$a,result$b),];
thelatemail
est-ce que quelqu'un avec plus de représentants que moi peut accepter cette réponse?
Josh
Si l'ordre et les noms doivent être comme dans la question:expand.grid(b=b,a=a)[2:1]
GKi
Notez que le titre est Combinaisons uniques - cette réponse résout le problème OP, mais si les 2 colonnes sont du même type de données et que vous appliquez expand.grid, vous aurez des permutations uniques, pas des combinaisons uniques
Brent
27

Le tidyrpackage fournit une alternative intéressante crossing, qui fonctionne mieux que la expand.gridfonction classique car (1) les chaînes ne sont pas converties en facteurs et (2) le tri est plus intuitif:

library(tidyr)

a <- c("ABC", "DEF", "GHI")
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

crossing(a, b)

# A tibble: 15 x 2
       a          b
   <chr>      <chr>
 1   ABC 2012-05-01
 2   ABC 2012-05-02
 3   ABC 2012-05-03
 4   ABC 2012-05-04
 5   ABC 2012-05-05
 6   DEF 2012-05-01
 7   DEF 2012-05-02
 8   DEF 2012-05-03
 9   DEF 2012-05-04
10   DEF 2012-05-05
11   GHI 2012-05-01
12   GHI 2012-05-02
13   GHI 2012-05-03
14   GHI 2012-05-04
15   GHI 2012-05-05
hypothèse
la source
13

Manquant dans ce vue d'ensemble est la CJfonction de-paquet. En utilisant:

library(data.table)
CJ(a, b, unique = TRUE)

donne:

      a          b
 1: ABC 2012-05-01
 2: ABC 2012-05-02
 3: ABC 2012-05-03
 4: ABC 2012-05-04
 5: ABC 2012-05-05
 6: DEF 2012-05-01
 7: DEF 2012-05-02
 8: DEF 2012-05-03
 9: DEF 2012-05-04
10: DEF 2012-05-05
11: GHI 2012-05-01
12: GHI 2012-05-02
13: GHI 2012-05-03
14: GHI 2012-05-04
15: GHI 2012-05-05

NOTE: depuis la version 1.12.2 nomme CJautomatiquement les colonnes résultantes (voir aussi ici et ici ).

Jaap
la source
4

Depuis la version 1.0.0, tidyrpropose sa propre version de expand.grid(). Il complète la famille existante de expand(), nesting()et crossing()avec une fonction de bas niveau qui fonctionne avec des vecteurs .

Par rapport à base::expand.grid():

Varie le premier élément le plus rapidement. Ne convertit jamais les chaînes en facteurs. N'ajoute aucun attribut supplémentaire. Renvoie un tibble, pas un bloc de données. Peut étendre n'importe quel vecteur généralisé, y compris les trames de données.

a <- c("ABC", "DEF", "GHI")
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

tidyr::expand_grid(a, b)

   a     b         
   <chr> <chr>     
 1 ABC   2012-05-01
 2 ABC   2012-05-02
 3 ABC   2012-05-03
 4 ABC   2012-05-04
 5 ABC   2012-05-05
 6 DEF   2012-05-01
 7 DEF   2012-05-02
 8 DEF   2012-05-03
 9 DEF   2012-05-04
10 DEF   2012-05-05
11 GHI   2012-05-01
12 GHI   2012-05-02
13 GHI   2012-05-03
14 GHI   2012-05-04
15 GHI   2012-05-05
tmfmnk
la source
3

vous pouvez utiliser la fonction de commande pour trier n'importe quel nombre de colonnes. pour votre exemple

df <- expand.grid(a,b)
> df
   Var1       Var2
1   ABC 2012-05-01
2   DEF 2012-05-01
3   GHI 2012-05-01
4   ABC 2012-05-02
5   DEF 2012-05-02
6   GHI 2012-05-02
7   ABC 2012-05-03
8   DEF 2012-05-03
9   GHI 2012-05-03
10  ABC 2012-05-04
11  DEF 2012-05-04
12  GHI 2012-05-04
13  ABC 2012-05-05
14  DEF 2012-05-05
15  GHI 2012-05-05

> df[order( df[,1], df[,2] ),] 
   Var1       Var2
1   ABC 2012-05-01
4   ABC 2012-05-02
7   ABC 2012-05-03
10  ABC 2012-05-04
13  ABC 2012-05-05
2   DEF 2012-05-01
5   DEF 2012-05-02
8   DEF 2012-05-03
11  DEF 2012-05-04
14  DEF 2012-05-05
3   GHI 2012-05-01
6   GHI 2012-05-02
9   GHI 2012-05-03
12  GHI 2012-05-04
15  GHI 2012-05-05`
Izan
la source