Reputation: 101
I have a dataframe (df) like this
name col1 col2
pippo A;B;C E;F;G;
pluto G;H X;Y;Z;E;O;D
I'd like to write all possible combinations between 1 element of col1 and 1 element of col 2 and for each returned as a dataframe, for example
name col1 col2
pippo A E
pippo A F
pippo A G
pippo B E
... and so on.
Considering that I have all alphabet letters and the number of elements in col1 and col2 can variate (from 1 element to 10), is it possible with R?
Upvotes: 1
Views: 41
Reputation: 887891
We can use crossing
after splitting the columns by ;
library(dplyr)
library(tidyr)
library(purrr)
df %>%
transmute(name, new = map2(strsplit(col1, ";"),
strsplit(col2, ";"), ~ crossing(col1 = .x, col2 = .y))) %>%
unnest(c(new))
-output
# A tibble: 21 x 3
# name col1 col2
# <chr> <chr> <chr>
# 1 pippo A E
# 2 pippo A F
# 3 pippo A G
# 4 pippo B E
# 5 pippo B F
# 6 pippo B G
# 7 pippo C E
# 8 pippo C F
# 9 pippo C G
#10 pluto G D
# … with 11 more rows
df <- structure(list(name = c("pippo", "pluto"), col1 = c("A;B;C",
"G;H"), col2 = c("E;F;G;", "X;Y;Z;E;O;D")), class = "data.frame",
row.names = c(NA,
-2L))
Upvotes: 2
Reputation: 160952
Base R. This is not as clear to read as akrun's answer, but it's just base R.
eg <- do.call(Map, c(
list(f=function(...) do.call(expand.grid,
lapply(list(...), function(s) strsplit(s, ";")[[1]]))),
dat[,-1]))
cbind.data.frame(name = rep(dat$name, sapply(eg, nrow)), do.call(rbind, eg))
# name col1 col2
# A;B;C.1 pippo A E
# A;B;C.2 pippo B E
# A;B;C.3 pippo C E
# A;B;C.4 pippo A F
# A;B;C.5 pippo B F
# A;B;C.6 pippo C F
# A;B;C.7 pippo A G
# A;B;C.8 pippo B G
# A;B;C.9 pippo C G
# G;H.1 pluto G X
# G;H.2 pluto H X
# G;H.3 pluto G Y
# G;H.4 pluto H Y
# G;H.5 pluto G Z
# G;H.6 pluto H Z
# G;H.7 pluto G E
# G;H.8 pluto H E
# G;H.9 pluto G O
# G;H.10 pluto H O
# G;H.11 pluto G D
# G;H.12 pluto H D
Upvotes: 2