{"spec_id":"choropleth-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' choropleth-basic: Choropleth Map with Regional Coloring\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 85/100 | Created: 2026-09-02\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(tibble)\nlibrary(scales)\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\"\nINK_MUTED   <- if (THEME == \"light\") \"#6B6A63\" else \"#A8A79F\"\n\n# --- Data -----------------------------------------------------------------\n# ggplot2 has no native geographic-boundary support (needs sf/ggmap, out of\n# scope here), so the map is expressed as a schematic unit-tile mosaic —\n# each South American country is a set of grid cells, laid out to preserve\n# real relative position/adjacency. geom_tile() then renders it natively.\ncell_list <- list(\n  Venezuela = matrix(c(2, 6, 3, 6, 2, 5), ncol = 2, byrow = TRUE),\n  Guyana    = matrix(c(4, 6), ncol = 2, byrow = TRUE),\n  Suriname  = matrix(c(5, 6), ncol = 2, byrow = TRUE),\n  Colombia  = matrix(c(0, 5, 1, 5, 0, 4, 1, 4, 1, 3), ncol = 2, byrow = TRUE),\n  Ecuador   = matrix(c(0, 3), ncol = 2, byrow = TRUE),\n  Peru      = matrix(c(0, 2, 1, 2, 0, 1), ncol = 2, byrow = TRUE),\n  Brazil    = matrix(c(\n    2, 4, 3, 4, 4, 4, 5, 4,\n    2, 3, 3, 3, 4, 3, 5, 3, 6, 3,\n    2, 2, 3, 2, 4, 2, 5, 2, 6, 2,\n    2, 1, 3, 1, 4, 1, 5, 1,\n    3, 0, 4, 0, 5, 0\n  ), ncol = 2, byrow = TRUE),\n  Bolivia   = matrix(c(1, 1, 2, 0, 1, 0), ncol = 2, byrow = TRUE),\n  Paraguay  = matrix(c(3, -1, 4, -1), ncol = 2, byrow = TRUE),\n  Chile     = matrix(c(0, 0, 0, -1, 0, -2, 0, -3, 0, -4, 0, -5, 0, -6), ncol = 2, byrow = TRUE),\n  Argentina = matrix(c(\n    1, -1, 2, -1,\n    1, -2, 2, -2,\n    1, -3, 2, -3,\n    1, -4,\n    1, -5,\n    1, -6\n  ), ncol = 2, byrow = TRUE),\n  Uruguay   = matrix(c(5, -1), ncol = 2, byrow = TRUE)\n)\n\ncountry_cells <- bind_rows(lapply(names(cell_list), function(country) {\n  cells <- cell_list[[country]]\n  tibble(country = country, col = cells[, 1], row = cells[, 2])\n}))\n\ncountry_code <- c(\n  Venezuela = \"VE\", Guyana = \"GY\", Suriname = \"SR\", Colombia = \"CO\",\n  Ecuador = \"EC\", Peru = \"PE\", Brazil = \"BR\", Bolivia = \"BO\",\n  Paraguay = \"PY\", Chile = \"CL\", Argentina = \"AR\", Uruguay = \"UY\"\n)\n\n# Renewable share of electricity generation (%) — Guyana is left NA to\n# demonstrate missing-data handling.\nrenewable_share <- tibble(\n  country = names(country_code),\n  value   = c(65, NA, 45, 70, 75, 60, 85, 30, 100, 48, 30, 94)\n)\n\ndf <- country_cells %>%\n  left_join(renewable_share, by = \"country\")\n\ncentroids <- df %>%\n  group_by(country) %>%\n  summarize(x = mean(col), y = mean(row), value = first(value), .groups = \"drop\") %>%\n  mutate(code = country_code[country])\n\ndf_present <- df %>% filter(!is.na(value))\ndf_missing <- df %>% filter(is.na(value))\n\n# Highest/lowest-share countries are named in the caption below (no on-map\n# marker: a per-cell highlight either creates seams across multi-cell\n# countries like Bolivia/Argentina or collides with their centroid label).\nextreme_countries <- df_present %>%\n  distinct(country, value) %>%\n  filter(value == max(value) | value == min(value)) %>%\n  mutate(code = country_code[country])\n\nhighest_codes <- extreme_countries %>%\n  filter(value == max(value)) %>%\n  pull(code) %>%\n  paste(collapse = \", \")\nhighest_value <- max(extreme_countries$value)\nlowest_codes <- extreme_countries %>%\n  filter(value == min(value)) %>%\n  pull(code) %>%\n  paste(collapse = \", \")\nlowest_value <- min(extreme_countries$value)\n\n# --- Title (fontsize scales with title length, see plot-generator.md) -----\n# No descriptive prefix: the legend title already names the metric, and the\n# square canvas leaves less horizontal room than the landscape default.\ntitle_text <- \"choropleth-basic · r · ggplot2 · anyplot.ai\"\ntitle_len   <- nchar(title_text)\ntitle_ratio <- if (title_len > 67) 67 / title_len else 1\ntitle_size  <- max(8, round(12 * title_ratio))\n\n# --- Plot -------------------------------------------------------------------\np <- ggplot() +\n  geom_tile(\n    data = df_present, aes(x = col, y = row, fill = value),\n    color = PAGE_BG, linewidth = 0.6, width = 0.94, height = 0.94\n  ) +\n  geom_tile(\n    data = df_missing, aes(x = col, y = row),\n    fill = INK_MUTED, color = PAGE_BG, linewidth = 0.6,\n    width = 0.94, height = 0.94, alpha = 0.6\n  ) +\n  geom_text(\n    data = centroids, aes(x = x, y = y, label = code),\n    size = 3, color = INK, fontface = \"bold\"\n  ) +\n  scale_fill_gradient(\n    low = \"#009E73\", high = \"#4467A3\",\n    name = \"Renewable share\\nof electricity\",\n    labels = label_percent(scale = 1),\n    na.value = INK_MUTED,\n    guide = guide_colorbar(frame.colour = INK_SOFT, ticks.colour = INK_SOFT)\n  ) +\n  coord_fixed(ratio = 1) +\n  labs(\n    title    = title_text,\n    subtitle = \"Schematic tile-map of South America · relative country adjacency preserved, not to scale\",\n    caption  = paste0(\n      \"Highest: \", highest_codes, \" (\", highest_value, \"%) · lowest: \",\n      lowest_codes, \" (\", lowest_value, \"%)\\nGray tile: data unavailable (Guyana)\"\n    )\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        = element_blank(),\n    axis.text         = element_blank(),\n    axis.title        = element_blank(),\n    axis.ticks        = element_blank(),\n    plot.title        = element_text(size = title_size, color = INK, hjust = 0.5),\n    plot.subtitle     = element_text(size = 7, color = INK_SOFT, hjust = 0.5),\n    plot.caption      = element_text(size = 7, color = INK_MUTED, hjust = 0.5),\n    legend.background = element_rect(fill = ELEVATED_BG, color = INK_SOFT),\n    legend.text       = element_text(size = 8, color = INK_SOFT),\n    legend.title      = element_text(size = 10, color = INK),\n    legend.position   = \"right\",\n    plot.margin       = margin(t = 12, r = 8, b = 8, l = 8)\n  )\n\n# --- Save -------------------------------------------------------------------\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"}