1

For a given n I would like to enumerate all 2^(n) - 1 possible subsets (excluding the null set).

So for n = 3 items (A, B, C) I have 8 - 1 combinations: {A}, {B}, {C}, {A, B}, {A, C}, {B, C}, and {A, B, C}.

To enumerate these subsets I would like to define a binary grid. For n = 3:

> expand.grid(0:1, 0:1, 0:1)[ -1, ]

  Var1 Var2 Var3
2    1    0    0
3    0    1    0
4    1    1    0
5    0    0    1
6    1    0    1
7    0    1    1
8    1    1    1

However, n is itself a random variable that changes from one simulation to the next.

It is easy to programmatically generate the string I need to pass to the function call. For instance, for n = 7, I can run:

> gsub(", $", "", paste(rep("0:1, ", 7), collapse = ""))

[1] "0:1, 0:1, 0:1, 0:1, 0:1, 0:1, 0:1"

But when I try to pass this string to expand.grid() I get an error. Surely there is a function that can coerce this string to a usable expression?

Timothy
  • 47
  • 5
  • Have you considered these solutions : https://stackoverflow.com/questions/27953588/unordered-combinations-of-all-lengths ? – Ronak Shah Oct 31 '20 at 01:35
  • Since R supports so many functions for combinations and permutations, I am not surprised there is a more direct solution. However, there are other times I wanted to pass a string to a function: for example, when iterating through many combinations of model parameters. The combinations example is for the sake of a reproducible prototype. – Timothy Oct 31 '20 at 01:40

2 Answers2

1

Running string as code is not recommended and should be avoided in general.

In this case, you can use replicate to repeat a vector n times and then use expand.grid with do.call.

n <- 3
do.call(expand.grid, replicate(n, list(0:1)))

#  Var1 Var2 Var3
#1    0    0    0
#2    1    0    0
#3    0    1    0
#4    1    1    0
#5    0    0    1
#6    1    0    1
#7    0    1    1
#8    1    1    1
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
1

We can use crossing

library(dplyr)
library(tidyr)
library(stringr)
library(purrr)
n <- 3
replicate(n, list(0:1)) %>%
    set_names(str_c('Var', seq_along(.))) %>% 
    invoke(crossing, .)
# 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
    
akrun
  • 874,273
  • 37
  • 540
  • 662