All N Combinations of All Subsets

Given the vector of elements, I would like to get a list of all possible combinations of n length subsets of elements. For example, given a (simplest) 1:2 sequence, I would like to get a form list object

 { {{1},{1}}, {{1},{2}}, {{2},{2}}, {{1},{1,2}}, {{2},{1,2}}, {{1,2},{1,2}} } 

when n=2 .

I managed to create a list of all nonempty subsets using the following:

 listOfAllSubsets <- function (s) { n <- length(s) unlist(lapply(1:n, function (n) { combn(s, n, simplify=FALSE) }), recursive=FALSE) } 

However, I'm not sure how best to move on. Essentially, I want the Cartesian product of this list with me (for n=2 ).

Any suggestions? An iterative solution (i.e., lack of for loops) would be preferable.

+5
source share
3 answers

This is what I would do, for example, with s=1:2 :

1) Imagine the subsets with a 0/1 matrix for each element.

 subsets = as.matrix(do.call(expand.grid,replicate(length(s),0:1,simplify=FALSE))) 

which gives

  Var1 Var2 [1,] 0 0 [2,] 1 0 [3,] 0 1 [4,] 1 1 

Here, the first line is an empty subset; the second, {1}; third, {2}; and fourth, {1,2}. To get a subset, use mysubset = s[subsets[row,]] , where row is the row of the desired subset.

2) Represent pairs of subsets as pairs of rows of a matrix:

 pairs <- expand.grid(Row1=1:nrow(subsets),Row2=1:nrow(subsets)) 

which gives

  Row1 Row2 1 1 1 2 2 1 3 3 1 4 4 1 5 1 2 6 2 2 7 3 2 8 4 2 9 1 3 10 2 3 11 3 3 12 4 3 13 1 4 14 2 4 15 3 4 16 4 4 

Here, the fourteenth line corresponds to the second and fourth lines of subsets , therefore {1} and {1,2}. This implies an order of paired questions (which implicitly assumes a Cartesian product). To restore the subsets, use mypairosubsets=lapply(pairs[p,],function(r) s[subsets[r,]]) , where p is the string of the pair you want.

The expansion outside the pair in the case of P(s)^n (where P(s) is the set of cardinality s ) will look like

 setsosets = as.matrix(do.call(expand.grid,replicate(n,1:nrow(subsets),simplify=FALSE))) 

Here, each line will have a vector of numbers. Each number corresponds to a row in the subsets matrix.


Creating instances of s elements is probably not necessary for what you do after that. However, you can do it here using lapply(1:nrow(pairs),function(p)lapply(pairs[p,],function(r) s[subsets[r,]])) , which starts as ...

 [[1]] [[1]]$Row1 integer(0) [[1]]$Row2 integer(0) [[2]] [[2]]$Row1 [1] 1 [[2]]$Row2 integer(0) 
+1
source

It is easier to start with the Cartesian product of indices. Duplication can then be avoided by making sure the index tuple is sorted.

 combosn <- function(items,n) { i <- seq_along(items) idx <-do.call(expand.grid,rep(list(i),n)) idx <- idx[!apply(idx,1,is.unsorted),] apply(idx,1,function(x) items[x]) } ss<-listOfAllSubsets(1:2) str(combosn(ss,2)) 
  List of 6
  $: List of 2
   .. $: int 1
   .. $: int 1
  $: List of 2
   .. $: int 1
   .. $: int 2
  $: List of 2
   .. $: int 2
   .. $: int 2
  $: List of 2
   .. $: int 1
   .. $: int [1: 2] 1 2
  $: List of 2
   .. $: int 2
   .. $: int [1: 2] 1 2
  $: List of 2
   .. $: int [1: 2] 1 2
   .. $: int [1: 2] 1 2

Or, for n=3 ,

 str(combosn(ss,3)) 
  List of 10
  $: List of 3
   .. $: int 1
   .. $: int 1
   .. $: int 1
  $: List of 3
   .. $: int 1
   .. $: int 1
   .. $: int 2
  $: List of 3
   .. $: int 1
   .. $: int 2
   .. $: int 2
  $: List of 3
   .. $: int 2
   .. $: int 2
   .. $: int 2
  $: List of 3
   .. $: int 1
   .. $: int 1
   .. $: int [1: 2] 1 2
  $: List of 3
   .. $: int 1
   .. $: int 2
   .. $: int [1: 2] 1 2
  $: List of 3
   .. $: int 2
   .. $: int 2
   .. $: int [1: 2] 1 2
  $: List of 3
   .. $: int 1
   .. $: int [1: 2] 1 2
   .. $: int [1: 2] 1 2
  $: List of 3
   .. $: int 2
   .. $: int [1: 2] 1 2
   .. $: int [1: 2] 1 2
  $: List of 3
   .. $: int [1: 2] 1 2
   .. $: int [1: 2] 1 2
   .. $: int [1: 2] 1 2
+3
source
 allSubsets<-function(n,# size of initial set m,# number of subsets includeEmpty=FALSE)# should the empty set be consiered a subset? { # m can't exceed the number of possible subsets if(includeEmpty) stopifnot(m <= 2^n) else stopifnot(m <= 2^n-1) # get the subsets of the initial set (of size n) if(includeEmpty){ ll <- split(t(combn(2^n,m)),seq(choose(2^n,m))) }else ll <- split(t(combn(2^n-1,m)),seq(choose(2^n-1,m))) # get the subets subsets <- apply(do.call(expand.grid,rep(list(c(F,T)),n)), 1,which) # remove the empty subset if desired if(!includeEmpty) subsets <- subsets[-1] # covert the subsets to vector subsets <- lapply(subsets,as.vector) # return the list of subsets apply(t(mapply('[',list(subsets),ll)),1,function(x)x) } # returns a list where each element is a list of length 2 with # subsets of the initial set of length 4 x = allSubsets(4,2,F) 
+1
source

Source: https://habr.com/ru/post/1212731/


All Articles