The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Modern maps with sf & projections

The legacy maps polygons are an unprojected plate carrée: they badly distort area and split Russia, Fiji and New Zealand across the antimeridian. The sf backend fixes all of this: real projections, equal-area options, and an antimeridian-safe pipeline. These features require the optional sf and rnaturalearth packages.

install.packages(c("sf", "rnaturalearth", "rnaturalearthdata"))

An equal-area, projected choropleth

world_data(2020, c(gdp = "NY.GDP.PCAP.KD"), geometry = "sf") |>
  world_map(gdp, style = "quantile", projection = "equal_earth",
            title = "GDP per capita (Equal Earth projection)")

world_map() auto-detects the sf backend and applies the projection through ggplot2::coord_sf(). Available projections are "equal_earth" (the default: equal-area and good-looking), "robinson", "mollweide", "natural_earth", "plate_carree", "mercator", "winkel_tripel", "eckert4", "gall_peters", "orthographic", "azimuthal_equal_area", "north_polar" and "south_polar".

projection_info() says what each one preserves, so you do not have to remember:

projection_info()[, c("projection", "property", "equal_area")]
#> # A tibble: 13 × 3
#>    projection           property    equal_area
#>    <chr>                <chr>       <lgl>     
#>  1 equal_earth          equal-area  TRUE      
#>  2 robinson             compromise  FALSE     
#>  3 mollweide            equal-area  TRUE      
#>  4 natural_earth        compromise  FALSE     
#>  5 plate_carree         equidistant FALSE     
#>  6 mercator             conformal   FALSE     
#>  7 winkel_tripel        compromise  FALSE     
#>  8 eckert4              equal-area  TRUE      
#>  9 gall_peters          equal-area  TRUE      
#> 10 orthographic         perspective FALSE     
#> 11 azimuthal_equal_area equal-area  TRUE      
#> 12 north_polar          equal-area  TRUE      
#> 13 south_polar          equal-area  TRUE

For a choropleth the equal-area ones are the honest choice, because the reader reads coloured area as quantity. projection_compare() draws your own data under several at once and tissot_map() shows the distortion directly (see the Honest maps vignette).

The world as a globe

globe_map() draws an orthographic globe centred on lon/lat. The default "sf" backend gives the cleanest limb; the "polygon" backend below needs only maps + mapproj (no sf):

globe_map(world_snapshot$countries, continent, backend = "polygon",
          style = "categorical", lon = 10, lat = 20)

Orthographic globe centred on the Indian Ocean, countries coloured by continent.

# With the sf backend (smoother limb, real great circles):
world_data(2020, geometry = "sf") |>
  globe_map(gdp_per_capita, lon = 10, lat = 30)

spin_globe() turns that into a rotating animation: one globe_map() frame per central longitude, assembled into a looping GIF with gifski (or magick):

spin_globe(world_snapshot$countries, continent, backend = "polygon",
           style = "categorical", n_frames = 60)

Just the canvas

world_geometry() returns projected, region-subset, antimeridian-safe geometry without any data: country polygons, label-ready centroids, coastlines, a graticule or an ocean rectangle:

africa <- world_geometry("countries", geometry = "sf", region = "Africa",
                         projection = "equal_earth")
ggplot(africa) +
  geom_sf(fill = "grey85", colour = "grey40", linewidth = 0.1) +
  theme_world_map()

Africa drawn on its own under an Equal Earth projection.

Recentring and the antimeridian

A Pacific-centred world is one argument away; the sf pipeline runs sf::st_break_antimeridian() before projecting, so nothing streaks across the frame:

world_geometry("countries", geometry = "sf", recenter = 150)

Region subsetting

region accepts a continent, a group name ("EU", "OECD", …), a vector of iso3c codes, or a bounding box c(xmin, ymin, xmax, ymax). Pair it with a projection suited to the subset (e.g. "azimuthal_equal_area" for a single continent, the polar projections for the Arctic) so the crop stays area-honest.

A box is the one form that clips the shapes themselves, which is what you want for a region that is neither a continent nor a group, the Mediterranean basin, say. Use the sf backend for it: that clip is a real sf::st_crop(), whereas the polygon backend can only drop the vertices outside the box and warns that a country crossing the edge comes back with an approximate outline.

med <- world_geometry("countries", geometry = "sf",
                      region = c(-10, 30, 40, 48), projection = "equal_earth")
ggplot(med) +
  geom_sf(fill = "grey85", colour = "grey40", linewidth = 0.1) +
  theme_world_map()

The Mediterranean basin cropped by bounding box under an Equal Earth projection.

Simplifying for the web

High-resolution geometry can be thinned for fast plotting with simplify_geometry() (which uses rmapshaper when available). scale = "medium" is the 50m Natural Earth data; "large" is 10m and additionally needs the rnaturalearthhires package, which is not on CRAN.

world_geometry(geometry = "sf", scale = "medium") |>
  simplify_geometry(keep = 0.1)

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.