Me deparei com esta pergunta aqui https://math.stackexchange.com/questions/2648895/why-does-fair-random-process-lead-to-unfair-result/5001301#5001301 na qual alguém estava interessado em simular um jogo em que dois jogadores dão dinheiro um ao outro aleatoriamente.
Usando R, tentei simular múltiplas trajetórias deste jogo para observar as distribuições de diferentes métricas:
library(ggplot2)
library(tidyverse)
library(gridExtra)
library(future)
library(furrr)
library(parallel)
n_cores <- detectCores() - 1
plan(multisession, workers = n_cores)
run_money_simulation <- function(n_sims, n_exchanges, player_a_start, player_b_start) {
set.seed(123)
sims_per_core <- ceiling(n_sims / n_cores)
simulate_exchange <- function(n_exchanges, player_a_start, player_b_start) {
person_a <- numeric(n_exchanges + 1)
person_b <- numeric(n_exchanges + 1)
person_a[1] <- player_a_start
person_b[1] <- player_b_start
for(i in 2:(n_exchanges + 1)) {
change <- sample(c(-1, 1), 1)
person_a[i] <- person_a[i-1] + change
person_b[i] <- person_b[i-1] - change
}
return(list(
final_diff = person_a[n_exchanges + 1] - person_b[n_exchanges + 1],
max_diff = max(abs(person_a - person_b)),
max_amount = max(c(max(person_a), max(person_b))),
min_amount = min(c(min(person_a), min(person_b)))
))
}
start_time <- Sys.time()
results <- future_map(1:n_sims, function(x) {
simulate_exchange(n_exchanges, player_a_start, player_b_start)
}, .options = furrr_options(seed = TRUE))
end_time <- Sys.time()
time_taken <- difftime(end_time, start_time, units = "secs")
final_diffs <- sapply(results, `[[`, "final_diff")
max_diffs <- sapply(results, `[[`, "max_diff")
max_amounts <- sapply(results, `[[`, "max_amount")
min_amounts <- sapply(results, `[[`, "min_amount")
plot_data <- tibble(
final_diff = final_diffs,
max_diff = max_diffs,
max_amount = max_amounts,
min_amount = min_amounts
) %>%
pivot_longer(everything(),
names_to = "metric",
values_to = "value")
main_plot <- ggplot(plot_data, aes(x = value)) +
geom_histogram(bins = 50, aes(fill = metric), color = "white", alpha = 0.7) +
facet_wrap(~metric, scales = "free", ncol = 2) +
scale_fill_manual(values = c("black", "red", "green4", "purple")) +
labs(title = paste("Money Exchange Simulation Results\n",
"Starting amounts: A =", player_a_start, ", B =", player_b_start),
subtitle = paste("Number of simulations:", n_sims,
"| Exchanges per simulation:", n_exchanges,
"\nProcessed using", n_cores, "CPU cores in",
round(time_taken, 2), "seconds"),
x = "Value",
y = "Count") +
theme_bw() +
theme(legend.position = "none")
print(main_plot)
invisible(list(
final_diffs = final_diffs,
max_diffs = max_diffs,
max_amounts = max_amounts,
min_amounts = min_amounts,
parameters = list(
n_sims = n_sims,
n_exchanges = n_exchanges,
player_a_start = player_a_start,
player_b_start = player_b_start,
n_cores = n_cores,
processing_time = time_taken
)
))
}
Quando eu chamo a função:
run_money_simulation(100000, 100, 100, 100)
Obtenho os seguintes resultados:
Só estou pensando: há algo que eu possa fazer no ggplot que detecte um formato de quebra de escala de modo que os espaços em branco nesses gráficos sejam removidos?
Tente adicionar
xlim(c(<lower_limit>, <upper_limit>))
. A partir daí, você pode criar outra função para encontrar onde fica o 90º percentil (ou outro limite) dos seus dados - insira isso em seus limites superior ou inferior.O problema é que você tem dados discretos. Histogramas são um tipo de estimativa de densidade, projetados para dados contínuos que realmente têm uma densidade.
Olhando para a figura superior esquerda
final_diff
, os dados mostrados são sempre múltiplos de 4. Como a largura do seu bin é ligeiramente menor que 4, alguns bins perdem completamente os dados. Você pode evitar as lacunas configurando a largura do bin para 4, mas essa não é a melhor solução. A melhor solução é usar um display projetado para dados discretos.A exibição usual para esse tipo de dado discreto é um gráfico de barras mostrando contagens de cada valor observado. Você pode obter isso usando
ggplot2
emgeom_bar()
vez degeom_histogram
. Por exemplo,Criado em 2024-11-21 com reprex v2.1.1
Isso parece mais feio do que um histograma, mas é mais fiel aos dados. E é menos feio em uma tela de resolução mais alta, onde você pode ver que todas as barras e espaços entre elas têm a mesma largura.