Interactive: Mean and variance of beta distribution
Summary
Interactive diagram for seeing how the mean and variance affect the shape of the beta distribution.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| viewerHeight: 770
library(shiny)
library(bslib)
library(ggplot2)
ui <- page_fluid(
title = "Beta distribution",
# Plot at the top
card(
card_header("Beta distribution plot"),
card_body(
uiOutput("plot_title"),
plotOutput("distPlot", height = "400px")
)
),
# Parameters below
card(
card_header("Distribution parameters"),
card_body(
layout_columns(
col_widths = c(6, 6),
sliderInput("mean", "Mean:", min = 0.1, max = 0.9, value = 0.5, step = 0.01),
sliderInput("variance", "Variance:", min = 0.01, max = 0.2, value = 0.05, step = 0.01)
)
)
)
)
server <- function(input, output, session) {
# Convert mean and variance to shape parameters
beta_params <- reactive({
mean_val <- input$mean
var_val <- input$variance
# For a beta distribution: mean = α/(α+β), var = αβ/((α+β)²(α+β+1))
# Solving for α and β given mean and variance:
# α = mean * ((mean * (1 - mean)) / variance - 1)
# β = (1 - mean) * ((mean * (1 - mean)) / variance - 1)
# Ensure variance doesn't exceed theoretical maximum
max_var <- mean_val * (1 - mean_val) / 1.01 # Small buffer
if (var_val >= max_var) {
var_val <- max_var
}
common_term <- (mean_val * (1 - mean_val)) / var_val - 1
alpha <- mean_val * common_term
beta <- (1 - mean_val) * common_term
# Ensure positive parameters
alpha <- max(alpha, 0.01)
beta <- max(beta, 0.01)
return(list(alpha = alpha, beta = beta))
})
# Display the plot title with distribution parameters
output$plot_title <- renderUI({
params <- beta_params()
title <- sprintf("Beta(α = %.2f, β = %.2f)", params$alpha, params$beta)
subtitle <- sprintf("Mean = %.2f, Variance = %.4f", input$mean, input$variance)
div(
tags$h4(title, style = "text-align: center; margin-bottom: 5px;"),
tags$p(subtitle, style = "text-align: center; color: gray; margin-bottom: 15px;")
)
})
# Generate the beta distribution plot
output$distPlot <- renderPlot({
# Get shape parameters
params <- beta_params()
shape1 <- params$alpha
shape2 <- params$beta
# Create data frame for plotting with fixed x range
x_values <- seq(0, 1, length.out = 500)
density_values <- dbeta(x_values, shape1 = shape1, shape2 = shape2)
plot_df <- data.frame(x = x_values, density = density_values)
# Create plot with fixed axes
p <- ggplot(plot_df, aes(x = x, y = density)) +
geom_line(size = 1, color = "#3F6BB6") +
geom_area(aes(x = x, y = density), fill = "#3F6BB6", alpha = 0.3) +
labs(x = "X", y = "Probability Density") +
theme_minimal() +
theme(panel.grid.minor = element_blank()) +
xlim(0, 1) +
ylim(0, 10) + # Fixed y-axis range
# Add reference line at mean
geom_vline(xintercept = input$mean, linetype = "dashed", color = "#DB4315", alpha = 0.7) +
annotate("text", x = input$mean + 0.08, y = 8.5, label = "Mean", color = "#DB4315", size = 4)
return(p)
})
}
shinyApp(ui = ui, server = server)
Further reading
Version history
v1.0: initial version created 08/24 by tdhc.