YesThatIsMe
YesThatIsMe

Reputation: 81

All combinations of elements of vectors at varying length with conditions to only pick one element per vector and disregarding order?

Imagine that we have three vectors:

v_1 = c("a", "b", "c", "d")
v_2 = c("e", "f", "g")
v_3 = c("h", "i")

I'd like to use R to retrieve a complete list of all combinations of these three vectors for all possible lengths under the condition that:

Given that I have done the math correctly, we should end up with 59 distinct combinations of lengths 1 to 3. I've looked into the combn() function, but it seems difficult (or impossible?) to apply the the two conditions. Does anyone a have suggestion for how to solve this in R?

Thanks!

Upvotes: 1

Views: 166

Answers (2)

lroha
lroha

Reputation: 34441

I think your general approach is sound but can be simplified by passing a list of your vectors directly to combn() and using expand.grid() in its function argument. Then all you need to do is bind the output into a data frame.

v_1 = c("a", " b", "c", "d")
v_2 = c("e", "f", "g")
v_3 = c("h", "i")

library(purrr)
library(dplyr)

my_list <- list(v_1, v_2, v_3)

map(seq_along(my_list), ~combn(my_list, .x, FUN = function(x) list(expand.grid(x, stringsAsFactors = FALSE)))) %>%
  map_df(bind_rows)

   Var1 Var2 Var3
1     a <NA> <NA>
2     b <NA> <NA>
3     c <NA> <NA>
4     d <NA> <NA>
5     e <NA> <NA>
6     f <NA> <NA>
7     g <NA> <NA>
8     h <NA> <NA>
9     i <NA> <NA>
10    a    e <NA>
...
58    c    g    i
59    d    g    i

Upvotes: 1

YesThatIsMe
YesThatIsMe

Reputation: 81

I added some more thoughts into this and this seems do the trick.

In the first step, I combined all the names of vectors:

vectors = c("v_1", "v_2", "v_3")

Second, I created a list of all mutually exclusive ways these three vectors could be combined:

list_comb_vectors = do.call("c", lapply(seq_along(vectors), function(i) combn(vectors, i, FUN = list)))

Thirdly, I created a function that goes through all of these combinations, i.e., 1 to length(list_comb_vectors). I finally make use of the expand.grid() function:

go_through_combination <- function(v) {

i = list_comb_vectors[[v]]

list_of_vars = do.call("c", lapply(seq_along(i), function(x) paste0(i[x],"=",i[x])))
list_of_expression = paste(list_of_vars, collapse=",")

eval(parse(text = paste0('expand.grid(', list_of_expression, ')')))

}

mapped <- map_df(1:length(list_comb_vectors), go_through_combination)

Even though this solves the issue, I'm sure there is a more elegant solution to the problem.

Upvotes: 0

Related Questions