---
title: "Beyond the choropleth"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Beyond the choropleth}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE, comment = "#>", message = FALSE, warning = FALSE,
  fig.width = 7, fig.height = 4, fig.align = "center", dpi = 96
)
library(countryatlas)
library(ggplot2)
snap <- world_snapshot$countries
# The sf geometry backend needs all three, which is what need_pkg() gates
# on in geometry.R: sf alone is not enough, and a chunk guarded on sf
# alone fails the vignette build wherever the data packages are absent.
has_sf <- requireNamespace("sf", quietly = TRUE) &&
  requireNamespace("rnaturalearth", quietly = TRUE) &&
  requireNamespace("rnaturalearthdata", quietly = TRUE)
```

"World data on a map" has many honest forms. A choropleth is only the first. The
package offers a full vocabulary; this vignette tours the ones that run without
extra dependencies and points to the rest.

## Proportional-symbol (bubble) maps

For *totals*, a choropleth misleads: large values hide in small countries. Sized
circles at centroids are the right idiom.

```{r}
bubble_map(snap, population)
```

## Spike maps

The same "totals" job as bubbles, with a different overplotting trade-off:
spikes only grow upward, so dense regions (Europe, the Caribbean) stay
legible.

```{r}
spike_map(snap, population)
```

## Equal-area tile grids

Give every country the same visual weight so micro-states are visible. The
bundled grid covers 239 countries -- see `?world_tiles` for the ten it
omits.

```{r fig.height = 5}
tile_map(snap, gdp_per_capita)
```

## Flow maps

Great-circle arcs between country pairs from an origin–destination table.

```{r}
od <- data.frame(
  from   = c("China", "Germany", "Brazil", "Nigeria"),
  to     = c("United States", "France", "Argentina", "India"),
  weight = c(500, 200, 90, 60)
)
flow_map(od, from, to, weight)
```

## Small multiples

`facet_map()` splits one choropleth into per-group panels — the static
counterpart to `animate_world()`, for print and side-by-side comparison:

```{r fig.height = 5}
world_poly <- attach_geometry(snap, geometry = "polygon") |>
  dplyr::filter(!is.na(continent))
facet_map(world_poly, gdp_per_capita, continent, style = "quantile", ncol = 3)
```

## Labels

Centroid-anchored labels (names, ISO codes or flag emoji), with `ggrepel`
collision avoidance when available.

```{r}
mapdf <- attach_geometry(
  dplyr::filter(snap, continent == "Europe"), geometry = "polygon"
)
world_map(mapdf, gdp_per_capita) +
  geom_country_labels(repel = FALSE, size = 2.5) +
  ggplot2::coord_cartesian(xlim = c(-25, 45), ylim = c(34, 72))
```

## Maps that need optional packages

The remaining displays follow the same one-call pattern but require optional
packages, so they are shown here as code:

```{r eval = FALSE}
# Bivariate choropleth (two variables at once) — needs `biscale` + `sf`
world_data(2020, c(gdp = "NY.GDP.PCAP.KD", life = "SP.DYN.LE00.IN"),
           geometry = "sf") |>
  bivariate_map(gdp, life)

# Area-honest cartogram — needs `cartogram` + `sf`
world_data(2020, c(pop = "SP.POP.TOTL"), geometry = "sf") |>
  cartogram_map(pop, type = "dorling")

# The same Dorling cartogram as a first-class verb, with its tuning exposed
world_data(2020, c(pop = "SP.POP.TOTL"), geometry = "sf") |>
  dorling_map(pop, k = 4)

# Animated choropleth over a year panel — needs `gganimate`
world_data(2000:2020, c(gdp = "NY.GDP.PCAP.KD")) |>
  animate_world(gdp)

# Interactive choropleth — needs `leaflet`, `ggiraph` or `plotly`
world_data(2020) |>
  interactive_map(gdp_per_capita, engine = "plotly")
```

## Country adjacency and distance

Two lightweight spatial helpers that aren't choropleths at all.
`distance_between()` answers "how far apart" from the bundled `country_meta`
centroids — no `sf` or network required:

```{r}
distance_between("France", "Germany")
```

`country_borders()` / `neighbors()` answer "who borders whom", built from
polygon topology, so they need `sf`:

```{r eval = has_sf}
neighbors("France")
```

Each degrades gracefully: if the optional package is missing you get a clear,
actionable message (and `animate_world()` falls back to a faceted
small-multiple).
