A major release that wires countryatlas into the database-rendering world via
'ggsql', widens the map vocabulary, and fixes several correctness issues found
by auditing 1.0.0. The version is bumped to 2.0.0 because the bug fixes change
the output of world_map() (quantile binning), bubble_map() / flow_map()
(de-duplicated symbols), geom_country_labels() (label placement) and
convert_country() (override-only entities) — code that depended on the old
behaviour may see different maps or values.
as_ggsql_source() exports a curated, ISO-reconciled, WDI-joined table (with
sf geometry WKB-encoded) as a ggsql source — a DuckDB
connection, a Parquet file, or a nanoarrow stream. countryatlas does the
reconciliation ggsql's static bundled world can't; ggsql does the database
push-down and Vega-Lite output countryatlas doesn't.world_query() emits a ggsql spatial query (VISUALISE … DRAW spatial PROJECT TO … SCALE … LABEL …) — a dependency-free string builder.interactive_map(engine = "ggsql") registers the data and renders the map in
DuckDB, returning a Vega-Lite widget.ggsql, duckdb, DBI and nanoarrow are optional Suggests. See the new
countryatlas and ggsql vignette.globe_map() — an orthographic globe choropleth, with backend = "sf"
(smoothest limb) or backend = "polygon" (needs only maps + mapproj).spin_globe() — a rotating-globe animated GIF (one globe_map() frame per
central longitude, assembled with gifski or magick).facet_map() — small-multiple choropleths (the static counterpart to
animate_world()).wdj_crs() gains eight projections (mercator, winkel_tripel, eckert4,
gall_peters, orthographic, azimuthal_equal_area, north_polar,
south_polar); world_map() / world_geometry() accept them all.locate_country() — point-in-polygon lookup tagging lon/lat with iso3c.repair_country_names() — the "act on it" companion to
check_country_match(): auto-applies confident string-distance fixes.country_join_all() — reduce-join many messy country tables on the ISO spine.growth_rate(), index_to(), share_of_world() — panel analysis helpers.country_overrides() — preferred name for wdj_overrides() (kept as an
alias) after the rename to countryatlas.country_groups_tbl gains Mercosur, GCC, Nordic and Visegrad.world_map(style = "quantile"/"jenks") computed breaks over polygon
vertices, so a country's geometric complexity biased the quantiles and the
bins held unequal numbers of countries. Breaks are now computed on one value
per country.bubble_map(backend = "sf") placed bubbles in projected metres on a degrees
base map (off the map). The base map and bubbles now share one projected CRS
via coord_sf().iso3c codes (overrides
map several names — Azores/Madeira → PRT — to one code), fanning out joins in
bubble_map() / flow_map(). Centroids are now one antimeridian-safe row per
country (the largest piece).geom_country_labels() placed labels at the bounding-box midpoint over all of
a country's pieces, so the US / Fiji / NZ labels drifted into the wrong ocean.
Labels now sit on each country's largest piece.projection = "plate_carree" built an incoherent PROJ string
(+proj=longlat … +units=m); it is now true equirectangular (+proj=eqc).convert_country() only applied wdj_overrides() for to = "iso3c", so
override-only entities (e.g. "Canary Islands") returned NA for derived
destinations. It now routes through the corrected iso3c first.A single, comprehensive release that takes the package from a one-function proof of concept to a complete toolkit for joining world data to maps. The spirit is unchanged — ISO codes as the universal join key, one call to a map-ready table — but pushed to its full potential.
world_data() is generalised but backward-compatible: world_data(2020)
still returns the classic polygon-backed, GDP-per-capita tibble. The only
visible change is the column name gdp_per_capita_2015 → gdp_per_capita.
A one-cycle deprecation shim keeps gdp_per_capita_2015 available as an alias
(toggle with options(countryatlas.gdp_compat = FALSE)).wdj_overrides()] instead of
deleted, so they appear on maps. Diffs of map output will show increased
coverage.world_data() gains indicator (one or many WDI codes; named vectors drive
clean column names), multi-year panels, an sf backend
(geometry = "sf"), region subsetting, latest, projections and caching.country_data() — the lightweight, one-row-per-country analysis table.world_geometry() — projected, region-subset geometry (countries, centroids,
coastline, borders, graticule, ocean).standardize_country(), join_world(), attach_geometry(), country_join().check_country_match(), wdj_overrides(), audit_coverage() — never lose a
country silently.convert_country() (flags, currency, tld, research codes), country_codes(),
country_groups() / in_group(), wdi_search().world_snapshot, country_meta, common_indicators,
country_groups_tbl, world_tiles.per_capita(), aggregate_regions(), rank_countries(), complete_years().world_map() (continuous / binned / quantile / jenks / categorical),
bubble_map(), bivariate_map(), cartogram_map(), tile_map(),
flow_map(), animate_world(), interactive_map(), geom_country_labels(),
theme_world_map().parallel::mclapply) where supported.
See clear_wdi_cache().world_snapshot lets every example, test and vignette run offline
and deterministically.@importFrom instead of blanket @import).cli / rlang errors.testthat (3e) suite; network calls are skipped offline and on CRAN.pkgdown site.sf, rnaturalearth, cartogram, biscale,
geofacet, gganimate, leaflet, …) are all in Suggests and gated by
rlang::check_installed(), so the base install stays light.Group memberships in country_groups_tbl are point-in-time as of 2024-01-01.
world_data(year) function.