{"spec_id":"boxen-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' boxen-basic: Basic Boxen Plot (Letter-Value Plot)\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 91/100 | Created: 2026-05-17\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(ragg)\nlibrary(tibble)\n\nset.seed(42)\n\n# --- Theme tokens -----------------------------------------------------------\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nIMPRINT   <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                 \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# --- Data -------------------------------------------------------------------\n# Simulate response time distributions across three server endpoints\nset.seed(42)\n\ndf <- tibble(\n  endpoint = c(\n    rep(\"API Search\", 3000),\n    rep(\"API Users\", 3000),\n    rep(\"API Reports\", 3000)\n  ),\n  response_time_ms = c(\n    c(rnorm(2700, mean = 50, sd = 15), rnorm(300, mean = 200, sd = 50)),\n    rnorm(3000, mean = 80, sd = 12),\n    c(rnorm(2500, mean = 120, sd = 25), rnorm(500, mean = 400, sd = 80))\n  )\n) %>%\n  mutate(response_time_ms = pmax(response_time_ms, 10))\n\n# --- Letter-Value Plot Construction -------------------------------------------\n# Compute quantiles at multiple levels for nested boxes: median, quartiles, eighths, sixteenths\ncompute_letter_values <- function(x) {\n  tibble(\n    level = c(4, 3, 2, 1, 0),  # sixteenths, eighths, quartiles, median, outliers\n    q_low = c(\n      quantile(x, 0.0625, na.rm = TRUE),   # 1/16\n      quantile(x, 0.125, na.rm = TRUE),    # 1/8\n      quantile(x, 0.25, na.rm = TRUE),     # 1/4\n      quantile(x, 0.5, na.rm = TRUE),      # median\n      quantile(x, 0.5, na.rm = TRUE)\n    ),\n    q_high = c(\n      quantile(x, 0.9375, na.rm = TRUE),   # 15/16\n      quantile(x, 0.875, na.rm = TRUE),    # 7/8\n      quantile(x, 0.75, na.rm = TRUE),     # 3/4\n      quantile(x, 0.5, na.rm = TRUE),      # median\n      quantile(x, 0.5, na.rm = TRUE)\n    ),\n    width_frac = c(0.25, 0.35, 0.55, 1.0, 0)\n  )\n}\n\n# Generate letter-value data for all groups\nlv_data <- df %>%\n  group_by(endpoint) %>%\n  reframe(compute_letter_values(response_time_ms))\n\n# Identify outliers beyond sixteenths\noutlier_data <- df %>%\n  group_by(endpoint) %>%\n  summarize(\n    q_low_16 = quantile(response_time_ms, 0.0625, na.rm = TRUE),\n    q_high_16 = quantile(response_time_ms, 0.9375, na.rm = TRUE),\n    .groups = \"drop\"\n  ) %>%\n  inner_join(\n    df,\n    by = \"endpoint\"\n  ) %>%\n  filter(response_time_ms < q_low_16 | response_time_ms > q_high_16) %>%\n  select(endpoint, response_time_ms)\n\n# --- Plot -------------------------------------------------------------------\n# Establish x-position and width mapping\nendpoints <- unique(lv_data$endpoint)\nx_pos <- seq_along(endpoints)\nnames(x_pos) <- endpoints\n\np <- ggplot() +\n  # Layer 1: Nested boxes (sixteenths, eighths, quartiles, median)\n  geom_rect(\n    data = lv_data %>% filter(level > 0),\n    aes(\n      xmin = as.numeric(factor(endpoint, levels = endpoints)) - 0.5 * width_frac,\n      xmax = as.numeric(factor(endpoint, levels = endpoints)) + 0.5 * width_frac,\n      ymin = q_low,\n      ymax = q_high,\n      fill = endpoint,\n      alpha = rev(0.15 + 0.2 * level)  # Darker/opaque for inner boxes\n    ),\n    color = INK_SOFT,\n    linewidth = 0.6\n  ) +\n  # Layer 2: Median line\n  geom_segment(\n    data = lv_data %>% filter(level == 1),\n    aes(\n      x = as.numeric(factor(endpoint, levels = endpoints)) - 0.55,\n      xend = as.numeric(factor(endpoint, levels = endpoints)) + 0.55,\n      y = q_low,\n      yend = q_low\n    ),\n    color = INK,\n    linewidth = 1.2\n  ) +\n  # Layer 3: Outliers\n  geom_point(\n    data = outlier_data,\n    aes(\n      x = as.numeric(factor(endpoint, levels = endpoints)),\n      y = response_time_ms,\n      fill = endpoint\n    ),\n    size = 3.5,\n    shape = 21,\n    color = INK_SOFT,\n    stroke = 1.2,\n    alpha = 0.75\n  ) +\n  scale_fill_manual(\n    name = \"Endpoint\",\n    values = IMPRINT[1:3],\n    breaks = endpoints\n  ) +\n  scale_alpha_identity() +\n  scale_x_continuous(\n    breaks = x_pos,\n    labels = names(x_pos),\n    limits = c(0.4, length(endpoints) + 0.6)\n  ) +\n  scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) +\n  labs(\n    title = \"boxen-basic · ggplot2 · anyplot.ai\",\n    subtitle = \"Letter-value plot: nested boxes show quantiles (sixteenths, eighths, quartiles)\",\n    x = \"Server Endpoint\",\n    y = \"Response Time (ms)\"\n  ) +\n  theme_minimal(base_size = 14) +\n  theme(\n    plot.background   = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background  = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major.x = element_blank(),\n    panel.grid.minor.y = element_blank(),\n    panel.grid.major.y = element_line(color = INK_SOFT, linewidth = 0.25),\n    panel.border      = element_blank(),\n    axis.line.x       = element_line(color = INK_SOFT, linewidth = 0.5),\n    axis.line.y       = element_line(color = INK_SOFT, linewidth = 0.5),\n    axis.title        = element_text(color = INK, size = 20, face = \"bold\"),\n    axis.text         = element_text(color = INK_SOFT, size = 16),\n    plot.title        = element_text(color = INK, size = 24, face = \"bold\"),\n    plot.subtitle     = element_text(color = INK_SOFT, size = 16, margin = margin(t = 8)),\n    legend.position   = \"right\",\n    legend.background = element_rect(fill = ELEVATED_BG, color = INK_SOFT, linewidth = 0.8),\n    legend.text       = element_text(color = INK_SOFT, size = 16),\n    legend.title      = element_text(color = INK, size = 18, face = \"bold\"),\n    legend.key        = element_blank(),\n    plot.margin       = margin(20, 20, 20, 20, \"pt\")\n  )\n\n# --- Save -------------------------------------------------------------------\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 16,\n  height   = 9,\n  units    = \"in\",\n  dpi      = 300\n)\n"}