Skip to content

24-7 Today

Menu
  • Home
  • Ads Guide
  • Blogging
  • Sec Tips
  • SEO Strategies
Menu

A Note on the Dirichlet Distribution

Posted on September 22, 2025 by 24-7

Code for helper functions
# This function generates the data frame for the animation
generate_dirichlet_animation_data <- function(alpha1_values, alpha2_values, alpha3_values, n_samples = 2000) {
  library(MCMCpack)
  
  # Triangle vertices
  v1 <- c(1, 0)
  v2 <- c(0, 1)
  v3 <- c(0, 0)
  
  # Projection function
  project_to_triangle <- function(x1, x2, x3) {
    x <- x1 * v1[1] + x2 * v2[1] + x3 * v3[1]
    y <- x1 * v1[2] + x2 * v2[2] + x3 * v3[2]
    data.frame(x = x, y = y)
  }
  
  # Generate animation data
  animation_data <- do.call(rbind, lapply(seq_along(alpha1_values), function(i) {
    alpha <- c(alpha1_values[i], alpha2_values[i], alpha3_values[i])
    samples <- rdirichlet(n_samples, alpha)
    projected <- project_to_triangle(samples[,1], samples[,2], samples[,3])
    projected$alpha1 <- alpha[1]
    projected$alpha2 <- alpha[2]
    projected$alpha3 <- alpha[3]
    projected$frame <- i
    projected
  }))
  
  return(animation_data)
}

# This function creates the animated plot
plot_dirichlet_evolution <- function(animation_data) {
  library(ggplot2)
  library(gganimate)
  library(grid)  # for arrow units
  
  # Triangle vertices
  v1 <- c(1, 0)
  v2 <- c(0, 1)
  v3 <- c(0, 0)
  
  # Label positions
  label_df <- data.frame(
    x = c(v1[1], v2[1], v3[1]),
    y = c(v1[2], v2[2], v3[2]),
    label = c("(1,0,0)", "(0,1,0)", "(0,0,1)"),
    nudge_x = c(-0.08, 0.1, 0),
    nudge_y = c(0, 0, 0.08)
  )
  
  # Triangle outline
  triangle_df <- data.frame(
    x = c(v1[1], v2[1], v3[1], v1[1]),
    y = c(v1[2], v2[2], v3[2], v1[2])
  )
  
  # Build plot
  p_animation <- ggplot(animation_data, aes(x = x, y = y)) +
    geom_point(alpha = 0.3, size = 0.8, color = "steelblue") +
    geom_density_2d(color = "red", alpha = 0.7) +
    geom_path(data = triangle_df, aes(x = x, y = y), color = "black", size = 1) +
    annotate("segment", x = 1, y = 0, xend = 0, yend = 1,
             arrow = arrow(length = unit(0.2, "cm")),
             color = "darkgreen", size = 1.2) +
    xlim(0, 1) + ylim(0, 1) +
    geom_text(data = label_df,
              aes(x = x, y = y, label = label),
              nudge_x = label_df$nudge_x,
              nudge_y = label_df$nudge_y,
              size = 4, fontface = "bold", color = "black") +
    labs(
      title = "Dirichlet Prior Evolution",
      subtitle = "",
      x = "Projected X",
      y = "Projected Y",
      caption = "Transition from uniform to concentrated distribution"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 16, hjust = 0.5),
      plot.subtitle = element_text(size = 14, hjust = 0.5),
      axis.title = element_text(size = 12),
      plot.caption = element_text(size = 10, hjust = 0.5)
    ) +
    transition_states(frame,
                      transition_length = 1,
                      state_length = 2) +
    ease_aes('sine-in-out')
  
  return(p_animation)
}

#| message: false
#| warning: false
#| code-fold: true
#| code-summary: "Animation Code"
#| 
set.seed(42)

# Parameters
alpha1_values <- seq(1, 0.1, by = -0.01)  # starts high, ends low
alpha2_values <- seq(1, 0.1, by = -0.01)   # starts low, ends high
alpha3_values <- seq(1, 0.1, by = -0.01)   # starts low, ends high

animation_data <- generate_dirichlet_animation_data(alpha1 = alpha1_values, 
                                                    alpha2 = alpha2_values, 
                                                    alpha3 = alpha3_values, 
                                                    n_samples = 2000)

plot_dirichlet_evolution(animation_data)

Related

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

©2025 24-7 Today | Design: WordPress | Design: Facts