{"spec_id":"scatter-marginal","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' scatter-marginal: Scatter Plot with Marginal Distributions\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 91/100 | Created: 2026-09-09\n\nlibrary(ggplot2)\nlibrary(gridExtra)\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\"\nGRID     <- if (THEME == \"light\") \"#CDCCC5\" else \"#454541\"\nIMPRINT_PALETTE <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                     \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\")\nBRAND <- IMPRINT_PALETTE[1]\n\n# --- Data ----------------------------------------------------------------\n# Annual rainfall vs. crop yield across 400 farm plots, moderately correlated.\nn <- 400\nrainfall_mm <- rnorm(n, mean = 800, sd = 150)\ncrop_yield_t_ha <- 1.5 + 0.0035 * rainfall_mm + rnorm(n, mean = 0, sd = 0.55)\ndf <- tibble::tibble(rainfall_mm = rainfall_mm, crop_yield_t_ha = crop_yield_t_ha)\n\nx_range <- range(df$rainfall_mm)\ny_range <- range(df$crop_yield_t_ha)\n\n# --- Shared chrome ---------------------------------------------------------\nanyplot_theme <- 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 = element_line(color = GRID, linewidth = 0.25),\n    panel.grid.minor = element_blank(),\n    axis.ticks       = element_blank()\n  )\n\n# --- Main scatter -----------------------------------------------------------\np_main <- ggplot(df, aes(rainfall_mm, crop_yield_t_ha)) +\n  geom_point(color = BRAND, size = 2.4, alpha = 0.6, stroke = 0) +\n  coord_cartesian(xlim = x_range, ylim = y_range) +\n  labs(x = \"Annual Rainfall (mm)\", y = \"Crop Yield (t/ha)\") +\n  anyplot_theme +\n  theme(\n    axis.line   = element_line(color = INK_SOFT, linewidth = 0.3),\n    axis.title  = element_text(color = INK, size = 11),\n    axis.text   = element_text(color = INK_SOFT, size = 10),\n    plot.margin = margin(t = 4, r = 4, b = 10, l = 10)\n  )\n\n# --- Top marginal: rainfall distribution ------------------------------------\np_top <- ggplot(df, aes(rainfall_mm)) +\n  geom_histogram(aes(y = after_stat(density)), bins = 30,\n                  fill = BRAND, color = NA, alpha = 0.3) +\n  geom_density(color = BRAND, linewidth = 0.6, alpha = 0.6) +\n  coord_cartesian(xlim = x_range) +\n  anyplot_theme +\n  theme(\n    axis.title  = element_blank(),\n    axis.text   = element_blank(),\n    plot.margin = margin(t = 10, r = 4, b = 2, l = 10)\n  )\n\n# --- Right marginal: crop yield distribution, flipped ------------------------\np_right <- ggplot(df, aes(crop_yield_t_ha)) +\n  geom_histogram(aes(y = after_stat(density)), bins = 30,\n                  fill = BRAND, color = NA, alpha = 0.3) +\n  geom_density(color = BRAND, linewidth = 0.6, alpha = 0.6) +\n  coord_flip(xlim = y_range) +\n  anyplot_theme +\n  theme(\n    axis.title  = element_blank(),\n    axis.text   = element_blank(),\n    plot.margin = margin(t = 4, r = 10, b = 10, l = 2)\n  )\n\n# --- Align marginal panels to the main scatter's panel geometry -------------\ng_main  <- ggplotGrob(p_main)\ng_top   <- ggplotGrob(p_top)\ng_right <- ggplotGrob(p_right)\ng_top$widths    <- g_main$widths\ng_right$heights <- g_main$heights\n\ntitle_grob <- grid::textGrob(\n  \"scatter-marginal · r · ggplot2 · anyplot.ai\",\n  x = 0, hjust = 0,\n  gp = grid::gpar(col = INK, fontsize = 12, fontface = \"plain\")\n)\n\ncomposite <- arrangeGrob(\n  grobs = list(title_grob, g_top, g_main, g_right),\n  layout_matrix = rbind(\n    c(1, 1),\n    c(2, NA),\n    c(3, 4)\n  ),\n  widths  = c(4, 1),\n  heights = c(0.5, 1, 4)\n)\n\n# --- Save --------------------------------------------------------------------\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = composite,\n  device   = ragg::agg_png,\n  width    = 6,\n  height   = 6,\n  units    = \"in\",\n  dpi      = 400,\n  bg       = PAGE_BG\n)\n"}