2026-03-26
Kinds of maps (outline vs. tiles; interactive vs. static)
Creating basic maps
Adding points
Shading areas
Tile service providers
Dynamic: leaflet for drawing raster or tiled maps (leafletjs.com)
Static: ggmap (part of tidyverse, tiles from several services)
Both rely on internet services such as:
| city | city_ascii | lat | lng | country | iso2 | iso3 | admin_name | capital | population | id |
|---|---|---|---|---|---|---|---|---|---|---|
| Tokyo | Tokyo | 35.6897 | 139.6922 | Japan | JP | JPN | Tōkyō | primary | 37977000 | 1392685764 |
| Jakarta | Jakarta | -6.2146 | 106.8451 | Indonesia | ID | IDN | Jakarta | primary | 34540000 | 1360771077 |
| Delhi | Delhi | 28.6600 | 77.2300 | India | IN | IND | Delhi | admin | 29617000 | 1356872604 |
| Mumbai | Mumbai | 18.9667 | 72.8333 | India | IN | IND | Mahārāshtra | admin | 23355000 | 1356226629 |
| Manila | Manila | 14.5958 | 120.9772 | Philippines | PH | PHL | Manila | primary | 23088000 | 1608618140 |
| Shanghai | Shanghai | 31.1667 | 121.4667 | China | CN | CHN | Shanghai | admin | 22120000 | 1156073548 |
canada_map <- rnaturalearth::ne_states(country = "canada", returnclass = "sf")
pal <- colorFactor(palette = "viridis", domain = canada_map$name)
m3a <- leaflet(canada_map) |>
addTiles() |> # Standard OpenStreetMap background
addPolygons(
fillColor = ~pal(name), # Fill based on province name
fillOpacity = 0.7,
color = "white", # Border color
weight = 1, # Border thickness
highlightOptions = highlightOptions(
weight = 3,
color = "#666",
bringToFront = TRUE),
label = ~name # Pop-up labels on hover
) |>
addLegend(
pal = pal,
values = ~name,
title = "Province",
position = "bottomright"
)pal <- colorNumeric("viridis", NULL) # make a viridis palette
my_values = runif(13, 0, 10) # random numbers between 0 and 10
m3b <- leaflet(canada_map) |>
addTiles() |> # Standard OpenStreetMap background
addPolygons(
fillColor = ~pal(my_values), # Fill based on province name
fillOpacity = 0.7,
color = "white", # Border color
weight = 1, # Border thickness
highlightOptions = highlightOptions(
weight = 3,
color = "#666",
bringToFront = TRUE),
label = ~name # Pop-up labels on hover
) |>
addLegend(
pal = pal,
values = ~my_values,
title = "Province",
position = "bottomright"
)Google maps have more options, but you must sign up for an API key first. These examples are for anyone who wants to experiment with that option.
See help for the package ggmap for more services (google maps, open street maps).
Start with a small integer for zoom and increase it if your map is fuzzy. (Don’t burden yourself or a free service by downloading unnecessary data.)
library(tidyterra)
library(maptiles)
library(sf)
bbox <- st_bbox(c(xmin = -130, ymin = 41, xmax = -50, ymax = 66), crs = 4326)
options(stadiamaps.key = "d652822b-6da3-4f0c-9cb5-d4e17f2a12d0")
bg_terrain <- get_tiles(bbox, provider = "Stadia.StamenTerrain", zoom = 5)
ggplot() +
geom_spatraster_rgb(data = bg_terrain) +
theme_minimal() +
labs(title = "Terrain Map of North America",
caption = "Basemap: Stadia/Stamen Terrain")# brew install proj gdal # on Mac; need homebrew too
# Sys.setenv(PROJ_LIB = "/opt/homebrew/share/proj")
# should just work on Windows
library(maptiles)
library(tidyterra)
library(sf)
# 1. Define your area (Halifax to a broader view of Canada)
bbox_canada <- st_bbox(c(xmin = -130, ymin = 41, xmax = -50, ymax = 66), crs = 4326)
# 2. Get the tiles - "Esri.WorldTerrain" is high quality and key-free
# You can also try "OpenTopoMap" for more of a topographic contour look
terrain_tiles <- get_tiles(bbox_canada, provider = "Esri.WorldTerrain", zoom = 5)
# 3. Plot using tidyterra for the best compatibility
ggplot() +
geom_spatraster_rgb(data = terrain_tiles) +
theme_minimal() +
labs(title = "Zero-Key Terrain Background",
subtitle = "Using Esri World Terrain Tiles",
caption = "Data: Esri, USGS, NOAA")Outline vs tiled (image) maps
Make a basic map
Add points and labels
Fill regions with colour (requires polygons)
There are several tile services, but free access comes and goes frequently