web-dev-qa-db-fra.com

produit cartésien avec dplyr R

J'essaie de trouver la fonction dplyr pour un produit cartésien. J'ai deux data.frame simples sans variable commune:

x <- data.frame(x=c("a","b","c"))
y <- data.frame(y=c(1,2,3))

Je voudrais reproduire le résultat de

merge(x,y)

  x y
1 a 1
2 b 1
3 c 1
4 a 2
5 b 2
6 c 2
7 a 3
8 b 3
9 c 3

J'ai déjà cherché cela (par exemple ici ou ici ) sans trouver quoi que ce soit d'utile.

Merci beaucoup

25
Luca Monno

Utilisez croisement du package tidyr:

x <- data.frame(x=c("a","b","c"))
y <- data.frame(y=c(1,2,3))

crossing(x, y)

Résultat:

   x y
 1 a 1
 2 a 2
 3 a 3
 4 b 1
 5 b 2
 6 b 3
 7 c 1
 8 c 2
 9 c 3
33
Gregor Sturm

Toutes mes excuses à tous: l'exemple ci-dessous ne pas semble fonctionner avec data.frames ou data.tables.

Lorsque x et y sont la base de données tbls (tbl_dbi/tbl_sql), Vous pouvez désormais également:

full_join(x, y, by = character())

Ajouté à dplyr fin 2017, et est également traduit en CROSS JOIN Dans le monde DB. Enregistre la méchanceté d'avoir à introduire les fausses variables.

7
dsz

Si nous avons besoin d'une sortie tidyverse, nous pouvons utiliser expand de tidyr

library(tidyverse)
y %>% 
   expand(y, x= x$x) %>%
   select(x,y)
# A tibble: 9 × 2
#       x     y
#  <fctr> <dbl>
#1      a     1
#2      b     1
#3      c     1
#4      a     2
#5      b     2
#6      c     2
#7      a     3
#8      b     3
#9      c     3
6
akrun

Face à ce problème, j'ai tendance à faire quelque chose comme ceci:

x <- data.frame(x=c("a","b","c"))
y <- data.frame(y=c(1,2,3))
x %>% mutate(temp=1) %>% 
inner_join(y %>% mutate(temp=1),by="temp") %>%
dplyr::select(-temp) 

Si x et y sont des trames de données à plusieurs colonnes, mais que je veux faire toutes les combinaisons d'une ligne de x avec une ligne de y, alors c'est plus propre que n'importe quelle option expand.grid () que je peux trouver

5
andyyy

Ceci est une continuation du commentaire de dsz. L'idée est venue de: http://jarrettmeyer.com/2018/07/10/cross-join-dplyr .

tbl_1$fake <- 1
tbl_2$fake <- 1
my_cross_join <- full_join(tbl_1, tbl_2, by = "fake") %>%
                 select(-fake)

J'ai testé cela sur quatre colonnes de données allant de 4 à 640 obs, et cela a pris environ 1,08 seconde.

3
Aaron C
expand.grid(x=c("a","b","c"),y=c(1,2,3))

Edit: Considérez également cette élégante solution suivante de " Y T " pour n data.frame plus complexe:

https://stackoverflow.com/a/21911221/5350791

en bref:

expand.grid.df <- function(...) Reduce(function(...) merge(..., by=NULL), list(...))
expand.grid.df(df1, df2, df3)
3
Damien Cormann