{"spec_id":"box-notched","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' box-notched: Notched Box Plot\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 87/100 | Created: 2026-08-18\n\nlibrary(ggplot2)\nlibrary(ragg)\n\nset.seed(42)\n\n# --- Theme tokens -------------------------------------------------------\nTHEME    <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG  <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK      <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\n\nIMPRINT_PALETTE <- c(\n  \"#009E73\",  # 1 — brand green\n  \"#C475FD\",  # 2 — lavender\n  \"#4467A3\",  # 3 — blue\n  \"#BD8233\",  # 4 — ochre\n  \"#AE3030\"   # 5 — matte red\n)\n\n# --- Data -----------------------------------------------------------------\n# Annual base salary (USD) by department. Sample sizes vary on purpose — the\n# smaller Marketing team (n = 45) shows a visibly wider notch than the larger\n# departments, illustrating the spec's \"notch reliability improves with\n# n > 20\" note directly in the chart.\ndepartments <- tibble::tibble(\n  department = factor(\n    rep(c(\"Engineering\", \"Sales\", \"Finance\", \"Support\", \"Marketing\"),\n        times = c(180, 150, 90, 110, 45)),\n    levels = c(\"Engineering\", \"Sales\", \"Finance\", \"Support\", \"Marketing\")\n  ),\n  salary = c(\n    rnorm(180, mean = 95000, sd = 18000),\n    rnorm(150, mean = 78000, sd = 22000),\n    rnorm(90, mean = 88000, sd = 12000),\n    rnorm(110, mean = 55000, sd = 10000),\n    rnorm(45, mean = 68000, sd = 15000)\n  )\n)\n\n# Reorder departments by descending median salary so adjacent notches are\n# easier to compare visually — the core point of a notched box plot.\ndepartments$department <- reorder(departments$department, -departments$salary, FUN = median)\n\n# --- Plot -------------------------------------------------------------------\np <- ggplot(departments, aes(x = department, y = salary, fill = department)) +\n  geom_boxplot(\n    notch = TRUE,\n    notchwidth = 0.6,\n    color = INK_SOFT,\n    linewidth = 0.5,\n    staplewidth = 0.4,\n    outlier.size = 2.2,\n    outlier.alpha = 0.6\n  ) +\n  scale_fill_manual(values = IMPRINT_PALETTE) +\n  scale_y_continuous(\n    breaks = scales::breaks_width(25000),\n    labels = scales::dollar_format(scale = 1e-3, suffix = \"k\")\n  ) +\n  labs(\n    title = \"box-notched · r · ggplot2 · anyplot.ai\",\n    x = \"Department\",\n    y = \"Annual Salary (USD)\"\n  ) +\n  theme_minimal(base_size = 8) +\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    = element_blank(),\n    panel.grid.major.y  = element_line(color = INK, linewidth = 0.3),\n    axis.title          = element_text(color = INK, size = 10),\n    axis.text           = element_text(color = INK_SOFT, size = 8),\n    axis.line           = element_line(color = INK_SOFT),\n    plot.title          = element_text(color = INK, size = 12),\n    legend.position      = \"none\"\n  )\n\n# --- Save -------------------------------------------------------------------\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 8,\n  height   = 4.5,\n  units    = \"in\",\n  dpi      = 400\n)\n"}