Repository navigation
R Stats: Combinations and Permutations
Abish Pius edited this page Feb 21, 2020
·
1 revision
- 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.
# 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"))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)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 matterhands <- 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)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 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)- 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.
# 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- 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)
# 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)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)# 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- 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.
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