Skip to content

R Stats: Combinations and Permutations

Abish Pius edited this page Feb 21, 2020 · 1 revision

Combinations and Permutations

  • paste() joins two strings and inserts a space in between.
  • expand.grid() gives the combinations of 2 vectors or lists.
  • permutations(n,r) from the gtools package lists the different ways that r items can be selected from a set of n options when order matters.
  • combinations(n,r) from the gtools package lists the different ways that r items can be selected from a set of n options when order does not matter.

Code: paste() and expand.grid()

# joining strings with paste
number <- "Three"
suit <- "Hearts"
paste(number, suit)

# joining vectors element-wise with paste
paste(letters[1:5], as.character(1:5))

# generating combinations of 2 vectors with expand.grid
expand.grid(pants = c("blue", "black"), shirt = c("white", "grey", "plaid"))

Code: Generate Deck of Playing Cards

suits <- c("Diamonds", "Clubs", "Hearts", "Spades")
numbers <- c("Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King")
deck <- expand.grid(number = numbers, suit = suits)
deck <- paste(deck$number, deck$suit)

# probability of drawing a king
kings <- paste("King", suits)
mean(deck %in% kings)

Code: Combinations and Permutations

library(gtools)
permutations(5,2)    # ways to choose 2 numbers in order from 1:5
all_phone_numbers <- permutations(10, 7, v = 0:9)
n <- nrow(all_phone_numbers)
index <- sample(n, 5)
all_phone_numbers[index,]

permutations(3,2)    # order matters
combinations(3,2)    # order does not matter

Code: Probability of drawing another king after a king is drawn

hands <- permutations(52,2, v = deck)
first_card <- hands[,1]
second_card <- hands[,2]
sum(first_card %in% kings)

sum(first_card %in% kings & second_card %in% kings) / sum(first_card %in% kings)

Code: Probability of a 21 in blackjack

hands <- permutations(52,2, v = deck)
first_card <- hands[,1]
second_card <- hands[,2]
sum(first_card %in% kings)

sum(first_card %in% kings & second_card %in% kings) / sum(first_card %in% kings)

Code: Monte Carlo Simulation of a 21 in blackjack

# code for one hand of blackjack
hand <- sample(deck, 2)
hand

# code for B=10,000 hands of blackjack
B <- 10000
results <- replicate(B, {
    hand <- sample(deck, 2)
    (hand[1] %in% aces & hand[2] %in% facecard) | (hand[2] %in% aces & hand[1] %in% facecard)
})
mean(results)

Example: The Birthday Problem

  • duplicated() takes a vector and returns a vector of the same length with TRUE for any elements that have appeared previously in that vector.
  • We can compute the probability of shared birthdays in a group of people by modeling birthdays as random draws from the numbers 1 through 365. We can then use this sampling model of birthdays to run a Monte Carlo simulation to estimate the probability of shared birthdays.

Code: Birthday Problem Example

# checking for duplicated bdays in one 50 person group
n <- 50
bdays <- sample(1:365, n, replace = TRUE)    # generate n random birthdays
any(duplicated(bdays))    # check if any birthdays are duplicated

# Monte Carlo simulation with B=10000 replicates
B <- 10000
results <- replicate(B, {    # returns vector of B logical values
    bdays <- sample(1:365, n, replace = TRUE)
    any(duplicated(bdays))
})
mean(results)    # calculates proportion of groups with duplicated birthdays

Advanced: The sapply function

  • Some functions automatically apply element-wise to vectors, such as sqrt() and *.
  • However, other functions do not operate element-wise by default. This includes functions we define ourselves.
  • The function sapply(x, f) allows any other function f to be applied element-wise to the vector x.
  • The probability of an event happening is 1 minus the probability of that event not happening:
    Pr(event)=1−Pr(no event)
  • We can compute the probability of shared birthdays mathematically:
    Pr(shared birthdays)=1−Pr(no shared birthdays)=1−(1×364/365×363/365×...×(365−n+1)/365)

Code: Birthday problem revisited

# function to calculate probability of shared bdays across n people
compute_prob <- function(n, B = 10000) {
	same_day <- replicate(B, {
    	bdays <- sample(1:365, n, replace = TRUE)
        any(duplicated(bdays))
    })
    mean(same_day)
}

n <- seq(1, 60)

Code: sapply Element-wise operation over vectors

x <- 1:10
sqrt(x)    # sqrt operates on each element of the vector

y <- 1:10
x*y    # * operates element-wise on both vectors

compute_prob(n)    # does not iterate over the vector n without sapply

x <- 1:10
sapply(x, sqrt)    # this is equivalent to sqrt(x)

prob <- sapply(n, compute_prob)    # element-wise application of compute_prob to n
plot(n, prob)

Code: Birthday problem with sapply

# function for computing exact probability of shared birthdays for any n
exact_prob <- function(n){
    prob_unique <- seq(365, 365-n+1)/365   # vector of fractions for mult. rule
    1 - prod(prob_unique)    # calculate prob of no shared birthdays and subtract from 1
}

# applying function element-wise to vector of n values
eprob <- sapply(n, exact_prob)

# plotting Monte Carlo results and exact probabilities on same graph
plot(n, prob)    # plot Monte Carlo results
lines(n, eprob, col = "red")    # add line for exact prob

An Aside into Monte Carlo: How Many Monte Carlo Experiments are Enough?

  • The larger the number of Monte Carlo replicates B, the more accurate the estimate.
  • Determining the appropriate size for B can require advanced statistics.
  • One practical approach is to try many sizes for B and look for sizes that provide stable estimates.

Code: Estimating B for Monte Carlo on Shared Birthday Example

B <- 10^seq(1, 5, len = 100)    # defines vector of many B values
compute_prob <- function(B, n = 22){    # function to run Monte Carlo simulation with each B
	same_day <- replicate(B, {
    	bdays <- sample(1:365, n, replace = TRUE)
        any(duplicated(bdays))
    })
    mean(same_day)
}

prob <- sapply(B, compute_prob)    # apply compute_prob to many values of B
plot(log10(B), prob, type = "l")    # plot a line graph of estimates 

Clone this wiki locally