Code
library(tidyverse)
Doing the basic Markov Chain Monte Carlo, recreating from: https://www.youtube.com/watch?v=rZk2FqX2XnY&t=2936s
library(tidyverse)
This is the function that creates the “rules” and probabilities
set.seed(123)
<- sort(runif(10, 1, 5000))
islands
<- c()
countz
<- 10
current
for(it in 1:50000) {
<- current - 1
island1
if (current == 1) {
<- 10
island1 else {
} <- current - 1
island1
}
if (current == 10) {
<- 1
island2 else {
} <- current + 1
island2
}
# 1= left, 2 = right
<- rbinom(1,1, 0.5) + 1
flip
<- islands[get(paste0("island", flip))]
num <- islands[current]
den
<- num/den
prob
if(prob > 1) {
<- 1
prob
}
#0 = stays
#1 = moves
<- rbinom(1,1, prob)
out
if (out == 0) {
<- current
current else {
} <- get(paste0("island", flip))
current
}
<- c(countz, current )
countz
}
::kable( data.frame("Island" = 1:length(islands), "Population" = islands)) kableExtra
Island | Population |
---|---|
1 | 228.7369 |
2 | 1438.6000 |
3 | 2045.4756 |
4 | 2283.6171 |
5 | 2640.9993 |
6 | 2757.6236 |
7 | 3941.7374 |
8 | 4415.2040 |
9 | 4462.2028 |
10 | 4702.3960 |
<- countz |>
plot_dat as.data.frame() |>
mutate(seq = factor(row_number()))
<- plot_dat |>
plot1 ggplot(aes(x = countz)) +
geom_histogram(binwidth = 1, color = "red", fill = NA) +
scale_x_continuous(breaks = 1:10) +
labs(x = "Islands",
y = "Visits") +
theme_minimal() +
theme(panel.grid.major.x = element_blank())
plot1
<- accumulate(c(50000, 1:6), ~ .x/2)
limitz_c
#Same as
# 50000 /2
#
# (50000 /2 )/2
#
# ((50000 /2 )/2)/2
#
# (((50000 /2 )/2)/2)/2
#
# ((((50000 /2 )/2)/2)/2)/2
<- 10000
limitz
<- plot_dat$countz[1:limitz] |>
labelz table() |>
as.data.frame() |>
mutate(Var1 = as.numeric(Var1))
%+%
plot1 subset(plot_dat, seq %in% 1:limitz) +
labs(title = paste0("Steps = ", limitz)) +
geom_label(data = labelz , aes(label = Freq, y = as.double(Freq), x = Var1))
<- 5
limitz
<- function(limitz) {
get_subplot
<- plot_dat$countz[1:limitz] |>
labelz table() |>
as.data.frame() |>
mutate(Var1 = as.numeric(as.character(Var1)))
<- plot1 %+%
plot_i subset(plot_dat, seq %in% 1:limitz) +
labs(title = paste0("Steps = ", limitz)) +
geom_label(data = labelz , aes(label = Freq, y = as.double(Freq), x = Var1))
return(plot_i)
}
require(gridExtra)
<- get_subplot(100)
p1 <- get_subplot(500)
p2 <- get_subplot(1000)
p3 <- get_subplot(10000)
p4 <- get_subplot(50000)
p5
grid.arrange(p1, p2, p3, p4, p5, nrow=2)
This is just to get the underlying data from each plot made with the above function
<- lapply(c(15, 20), function(x) {
comp_ls get_subplot(x) |>
with(data) |>
mutate(limit_group = x)
})
<- bind_rows(comp_ls) comp
This is just shows each step, up until the 1000 step
|>
plot_dat head(1000) |>
mutate(gr = "gr",
seq = as.numeric(seq)) |>
ggplot(aes(x = seq, y = countz, group = gr)) +
geom_point() +
geom_line() +
scale_y_continuous(breaks = 1:100) +
scale_x_continuous(n.breaks = 10) +
labs(x = "Step", y = "Island") +
theme_minimal()
This is just shows the accumualtion of visits over time
<- factor(countz, levels = 1:10)
countz2
<- sapply(1:length(countz2), function(x) table(countz2[1:x]))
rev
<- t(rev)
m
<- as.data.frame(m[1:1000, 1:10]) |>
df rename_with( ~ paste0("island_", .x)) |>
mutate(step = row_number()) |>
pivot_longer(cols = starts_with("island"),
names_to = "island",
values_to = "visits")
<- colorRampPalette(c("#faae7b", "#432371"))
color_fx <- color_fx(10)
color1 names(color1) <- unique(df$island)
|>
df mutate(island2 = factor(island),
island3 = as.numeric(gsub("island_", "", island))) |>
ggplot(aes(x = step, y = visits, group = island2, color = island2)) +
geom_point() +
scale_color_manual(values = color1,
aesthetics = "color") +
theme_minimal()
# Same but with different color spectrum set-up
# df |>
# mutate(island2 = factor(island),
# island3 = as.numeric(gsub("island_", "", island))) |>
# ggplot(aes(x = step, y = visits, group = island3, color = island3)) +
# geom_point() +
# scale_color_steps( high = "#432371", low = "#faae7b") +
# theme_minimal()
Taken from: https://rpruim.github.io/Kruschke-Notes/markov-chain-monte-carlo-mcmc.html
<- function(
KingMarkov num_steps = 1e5,
population = 1:5,
island_names = 1:length(population),
start = 1,
J = function(a, b) {1 / (length(population) - 1)}
) {
<- length(population)
num_islands <- rep(NA, num_steps) # trick to pre-alocate memory
island_seq <- rep(NA, num_steps) # trick to pre-alocate memory
proposal_seq <- start
current <- NA
proposal
for (i in 1:num_steps) {
# record current island
<- current
island_seq[i] <- proposal
proposal_seq[i]
# propose one of the other islands
<- setdiff(1:num_islands, current)
other_islands <-
proposal sample(other_islands, 1,
prob = purrr::map(other_islands, ~ J(current, .x)))
# move?
<- population[proposal] / population[current]
prob_move # new current island (either current current or proposal)
<- ifelse(runif(1) < prob_move, proposal, current)
current
}tibble(
step = 1:num_steps,
island = island_names[island_seq],
proposal = island_names[proposal_seq]
) }