{"spec_id":"heatmap-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' heatmap-basic: Basic Heatmap\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 91/100 | Created: 2026-05-28\n\nlibrary(ggplot2)\nlibrary(tidyr)\nlibrary(ragg)\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\"\nDIV_MID     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\n\n# Data: pairwise correlations across mtcars vehicle performance metrics\ndata(mtcars)\nselected_vars <- c(\"mpg\", \"cyl\", \"disp\", \"hp\", \"drat\", \"wt\", \"qsec\", \"gear\")\nvar_labels    <- c(\"MPG\", \"Cylinders\", \"Displacement\", \"Horsepower\",\n                   \"Rear Axle\", \"Weight\", \"1/4 Mile\", \"Gears\")\n\ncor_mat           <- cor(mtcars[, selected_vars])\nrownames(cor_mat) <- var_labels\ncolnames(cor_mat) <- var_labels\n\n# Reorder variables by hierarchical clustering — groups similar variables together\nhc_order  <- hclust(as.dist(1 - cor_mat))$order\nhc_labels <- var_labels[hc_order]\n\n# Reshape to long format\ncor_df       <- as.data.frame(cor_mat)\ncor_df$y_var <- rownames(cor_df)\ncor_long     <- pivot_longer(cor_df, cols = -y_var,\n                             names_to = \"x_var\", values_to = \"correlation\")\n\n# Lower triangle masking (including diagonal) to eliminate redundancy\nx_idx    <- match(cor_long$x_var, hc_labels)\ny_idx    <- match(cor_long$y_var, hc_labels)\ncor_long <- cor_long[y_idx >= x_idx, ]\n\n# Apply clustered ordering; reverse y levels so diagonal runs top-left to bottom-right\ncor_long$x_var <- factor(cor_long$x_var, levels = hc_labels)\ncor_long$y_var <- factor(cor_long$y_var, levels = rev(hc_labels))\n\n# Mark diagonal cells and strong off-diagonal correlations for visual treatment\ncor_long$on_diag   <- as.character(cor_long$x_var) == as.character(cor_long$y_var)\ncor_long$is_strong <- abs(cor_long$correlation) > 0.7 & !cor_long$on_diag\n\nplot_title    <- \"heatmap-basic · r · ggplot2 · anyplot.ai\"\nplot_subtitle <- \"MPG clusters negatively with Weight, Displacement, and Cylinders\"\n\np <- ggplot(cor_long, aes(x = x_var, y = y_var, fill = correlation)) +\n  geom_tile(color = PAGE_BG, linewidth = 0.8) +\n  # Highlight border on strong off-diagonal correlations (|r| > 0.7)\n  geom_tile(data = cor_long[cor_long$is_strong, ],\n            fill = NA, color = INK, linewidth = 1.0) +\n  # Off-diagonal annotations in INK; diagonal (trivial 1.00) in INK_SOFT\n  geom_text(data = cor_long[!cor_long$on_diag, ],\n            aes(label = sprintf(\"%.2f\", correlation)),\n            color = INK, size = 3.0) +\n  geom_text(data = cor_long[cor_long$on_diag, ],\n            aes(label = sprintf(\"%.2f\", correlation)),\n            color = INK_SOFT, size = 3.0) +\n  scale_fill_gradient2(\n    low      = \"#AE3030\",\n    mid      = DIV_MID,\n    high     = \"#4467A3\",\n    midpoint = 0,\n    limits   = c(-1, 1),\n    name     = \"r\"\n  ) +\n  coord_fixed() +\n  labs(title = plot_title, subtitle = plot_subtitle, x = NULL, y = NULL) +\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.border      = element_rect(color = INK_SOFT, fill = NA, linewidth = 0.3),\n    panel.grid        = element_blank(),\n    axis.text.x       = element_text(color = INK_SOFT, size = 9,\n                                     angle = 35, hjust = 1),\n    axis.text.y       = element_text(color = INK_SOFT, size = 9),\n    plot.title        = element_text(color = INK, size = 12, face = \"bold\",\n                                     margin = margin(b = 4)),\n    plot.subtitle     = element_text(color = INK_SOFT, size = 9,\n                                     margin = margin(b = 10)),\n    legend.background = element_rect(fill = ELEVATED_BG, color = NA),\n    legend.text       = element_text(color = INK_SOFT, size = 8),\n    legend.title      = element_text(color = INK, size = 10),\n    plot.margin       = margin(20, 20, 20, 20)\n  )\n\n# Save — square canvas (2400×2400 px = 6in × 6in @ 400 dpi)\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 6,\n  height   = 6,\n  units    = \"in\",\n  dpi      = 400\n)\n"}