Prradep
Prradep

Reputation: 5696

How to generate stratified permutations in R

I would like to generate different possible permutations with the same frequency as in the input vector. For example, I would like to generate the permutations using the vector x in the below example.

library(gtools)
x <- c('A','A','B')
permutations(2, 3, x, repeats.allowed = T)

It gives the below output.

#     [,1] [,2] [,3]
# [1,] "A"  "A"  "A" 
# [2,] "A"  "A"  "B" 
# [3,] "A"  "B"  "A" 
# [4,] "A"  "B"  "B" 
# [5,] "B"  "A"  "A" 
# [6,] "B"  "A"  "B" 
# [7,] "B"  "B"  "A" 
# [8,] "B"  "B"  "B" 

But, I want only permutations having A, B with frequencies 2, 1 respectively. The expected output is:

#     [,1] [,2] [,3]
# [1,] "A"  "A"  "B" 
# [2,] "A"  "B"  "A" 
# [3,] "B"  "A"  "A" 

Is there any function available in R?

Note: I do not want to do post-processing of the output to get the expected output as my original input contains 300 elements. It is not recommended to generate factorial(300) number of permutations.

Update: The suggested link provides a nice faster solution but fails when the input vector is doubled (eg: length=20) with the error message:

Error in matrix(NA, nrow = N, ncol = prod(sapply(foo, ncol))) :
invalid 'ncol' value (too large or NA)

Upvotes: 2

Views: 479

Answers (1)

Artem Sokolov
Artem Sokolov

Reputation: 13691

Your problem can be reformulated as finding all possible permutations of the frequency vector. Take a look at combinat::permn:

x <- c( 'A', 'A', 'B' )
unique(combinat::permn( x ))

# [[1]]
# [1] "A" "A" "B"

# [[2]]
# [1] "A" "B" "A"

# [[3]]
# [1] "B" "A" "A"

unique is necessary to remove duplicate entries, which is automatically done by gtools::permutations you've been using (through the default set=TRUE argument).

If you need the result in matrix format, as in your original question, pass the output as arguments to rbind using do.call:

do.call( rbind, unique(combinat::permn( x )) )
#      [,1] [,2] [,3]
# [1,] "A"  "A"  "B" 
# [2,] "A"  "B"  "A" 
# [3,] "B"  "A"  "A" 

Upvotes: 2

Related Questions