{"spec_id":"histogram-kde","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' histogram-kde: Histogram with KDE Overlay\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 87/100 | Created: 2026-08-05\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\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\n# ggplot2 has no grid-line alpha, so blend INK 20% toward PAGE_BG for a subtle tint\nGRID_COLOR  <- grDevices::colorRampPalette(c(PAGE_BG, INK))(100)[20]\nIMPRINT_PALETTE <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                     \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\")\n\n# --- Data ----------------------------------------------------------------\n# Daily returns of a hypothetical equity index (%) — a Student-t generator\n# gives the fat tails and mild negative skew typical of real return series,\n# which the histogram bins obscure but the KDE curve reveals cleanly.\nn_days <- 700\ndaily_returns <- (rt(n_days, df = 6) * 0.7 - 0.04 * rchisq(n_days, df = 2))\n\ndf <- tibble::tibble(return_pct = daily_returns)\n\n# --- Plot ----------------------------------------------------------------\np <- ggplot(df, aes(x = return_pct)) +\n  geom_histogram(\n    aes(y = after_stat(density), fill = \"Observed frequency\"),\n    bins = 40, color = PAGE_BG, linewidth = 0.2, alpha = 0.5\n  ) +\n  geom_density(\n    aes(color = \"KDE estimate\"),\n    linewidth = 1.3, adjust = 1.1\n  ) +\n  scale_fill_manual(name = NULL, values = c(\"Observed frequency\" = IMPRINT_PALETTE[1])) +\n  scale_color_manual(name = NULL, values = c(\"KDE estimate\" = IMPRINT_PALETTE[2])) +\n  labs(\n    title = \"histogram-kde · r · ggplot2 · anyplot.ai\",\n    x = \"Daily Return (%)\",\n    y = \"Density\"\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.x = element_blank(),\n    panel.grid.major.y = element_line(color = GRID_COLOR, linewidth = 0.3),\n    panel.grid.minor.y = element_blank(),\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, face = \"bold\"),\n    legend.position          = \"inside\",\n    legend.position.inside   = c(0.86, 0.86),\n    legend.background        = element_rect(fill = ELEVATED_BG, color = INK_SOFT),\n    legend.text              = element_text(color = INK_SOFT, size = 8),\n    legend.title             = element_blank(),\n    legend.key               = element_rect(fill = ELEVATED_BG, color = NA)\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"}