library(tidyverse, quietly = TRUE)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.0 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggmap)
## ℹ Google's Terms of Service: <https://mapsplatform.google.com>
## Stadia Maps' Terms of Service: <https://stadiamaps.com/terms-of-service/>
## OpenStreetMap's Tile Usage Policy: <https://operations.osmfoundation.org/policies/tiles/>
## ℹ Please cite ggmap if you use it! Use `citation("ggmap")` for details.
# library(rnaturalearth)
# library(rnaturalearthdata) # devtools::install_github("ropensci/rnaturalearthdata")
# library(rnaturalearthhires) # devtools::install_github("ropensci/rnaturalearthhires")
Lots of other packages in examples (notes and wider internet):
sf
(simple features), terra
, and many
more.
map_data
(get data for a map, part of ggplot2)geom_map
(draw a map)
map_id
(column with names for each region
to be plotted), required argument: map
(a data frame with
the map data)expand_limits
(if part of your map is not showing)coord_map
(projections, Mercator is default)m1 <- map_data("world")
m1lake <- map_data("lakes")
# m1 |> filter(region == "Canada")
# france, italy, lakes, nz, county (USA), state (USA), usa (coastline), world, world2 (centered on Pacific Ocean)
# canada.cities, world.cities
# see: help(package = "maps") for details
There are many “regions” and “subregions” within some of these maps:
count(m1, region) |> head()
## region n
## 1 Afghanistan 410
## 2 Albania 113
## 3 Algeria 383
## 4 American Samoa 8
## 5 Andorra 19
## 6 Angola 338
m1 |> filter(region == "Canada") |> count(subregion)
## subregion n
## 1 10 6
## 2 100 37
## 3 103 21
## 4 106 11
## 5 11 12
## 6 110 19
## 7 122 10
## 8 123 14
## 9 126 24
## 10 127 17
## 11 128 22
## 12 131 29
## 13 140 22
## 14 146 12
## 15 15 8
## 16 22 7
## 17 27 412
## 18 40 8
## 19 42 9
## 20 43 14
## 21 45 12
## 22 46 18
## 23 49 13
## 24 5 6
## 25 50 9
## 26 54 12
## 27 55 8
## 28 56 12
## 29 58 15
## 30 60 14
## 31 61 9
## 32 62 12
## 33 63 14
## 34 64 14
## 35 65 10
## 36 66 9
## 37 67 12
## 38 71 8
## 39 85 9
## 40 86 12
## 41 87 17
## 42 9 9
## 43 90 7
## 44 93 9
## 45 99 14
## 46 Air Force Island 21
## 47 Akpatok Island 16
## 48 Amund Ringnes Island 67
## 49 Anticosti Island 27
## 50 Aristazabal Island 13
## 51 Axel Heiberg Island 307
## 52 BC 15
## 53 Baffin Island 1440
## 54 Banks Island 145
## 55 Bathurst Island 169
## 56 Belcher Island 59
## 57 Bell Island 11
## 58 Big Island 20
## 59 Borden Island 45
## 60 Bray Island 22
## 61 Brock Island 24
## 62 Byam Martin Island 25
## 63 Bylot Island 56
## 64 Calvert Island 15
## 65 Cameron Island 27
## 66 Cape Breton Island 80
## 67 Chapman Lewes Island 11
## 68 Charles Island 13
## 69 Charlton Island 12
## 70 Coats Island 35
## 71 Coburg Island 16
## 72 Cornwall Island 25
## 73 Cornwallis Island 53
## 74 Devon Island 331
## 75 Edgell Island 19
## 76 Eglinton Island 23
## 77 Ellef Ringnes Island 126
## 78 Ellesmere Island 771
## 79 Emerald Isle 13
## 80 Flores Island 8
## 81 Fogo Island 12
## 82 Foley Island 21
## 83 Galiano Island 8
## 84 Gateshead Island 15
## 85 Graham Island 58
## 86 Grand Manan Island 7
## 87 Harrison Island 14
## 88 Helena Island 13
## 89 Herschel Island 9
## 90 Ile Lameque 10
## 91 Ile du Cap aux Meule 20
## 92 Jenny Lind Island 16
## 93 Jens Munk Island 38
## 94 King Christian Island 20
## 95 King William Island 104
## 96 Koch Island 20
## 97 Loks Land Island 17
## 98 Lougheed Island 27
## 99 Mackenzie King Island 52
## 100 Mansel Island 33
## 101 Matty Island 32
## 102 Meighen Island 27
## 103 Melbourne Island 16
## 104 Melville Island 297
## 105 Merasheen Island 12
## 106 Mill Island 11
## 107 Moresby Island 51
## 108 New World Island 16
## 109 Newfoundland 455
## 110 Nootka Island 17
## 111 North Kent Island 26
## 112 Nottingham Island 20
## 113 Porcher Island 25
## 114 Prescott Island 18
## 115 Prince Charles Island 39
## 116 Prince Edward Island 77
## 117 Prince Patrick Island 160
## 118 Prince of Wales Island 220
## 119 Princess Royal Island 29
## 120 Quadra Island 14
## 121 Redonda Island 11
## 122 Resolution Island 20
## 123 Royal Geographical Society Island 39
## 124 Russell Island 27
## 125 Sable Island 9
## 126 Salisbury Island 9
## 127 Saltspring Island 11
## 128 Smith Island 9
## 129 Somerset Island 90
## 130 Southampton Island 134
## 131 Stefansson Island 33
## 132 Texada Island 13
## 133 Tukarak Island 16
## 134 Vancouver Island 166
## 135 Vansittart Island 44
## 136 Victoria Island 427
## 137 Wales Island 28
## 138 White Island 24
## 139 Winter Island 12
## 140 <NA> 3317
Political borders and territorial disputes: maps will undoubtedly be incomplete, inaccurate, or conflict with some people’s political views whether in Canada (Québec, Labrador), France (St Pierre & Miquelon), China, Palestine, Russia, etc.
ggplot(m1, aes(map_id = region)) +
geom_map(fill = "darkred", color = NA,
linewidth = 0.1, map = m1, alpha = 0.5) +
expand_limits(x = c(-180,180), y = c(-85, 85) )
Combine the land and lake maps.
ggplot(m1, aes(map_id = region)) +
geom_map(data = m1, fill = "white", color = "black",
linewidth = 0.2, alpha = 1, map = m1) +
geom_map(data = m1lake, map = m1lake,
fill = "blue", color = NA) +
expand_limits(x = c(-180,180), y = c(-85, 85) )
Show just one region
m2 <- m1 |> filter(region == "Canada")
m2 |> summarize(min_lat = min(lat), max_lat = max(lat),
min_long = min(long), max_long = max(long))
## min_lat max_lat min_long max_long
## 1 41.67485 83.11611 -141.0022 -52.65366
ggplot(m2, aes(map_id = region)) +
geom_map(fill = "white", color = "black", linewidth = 0.5, map = m2) +
coord_map("albers", 60, 90) +
# coord_map("lambert", 42, 50) +
theme(axis.title = element_blank(), axis.text = element_blank(),
axis.ticks = element_blank()) +
expand_limits(x = c(-141, -50), y = c(41, 85))
ggplot(m2, aes(map_id = region)) +
geom_map(fill = "white", color = "black", linewidth = 0.5, map = m2) +
coord_map("lambert", 42, 50) +
theme(axis.title = element_blank(), axis.text = element_blank(),
axis.ticks = element_blank()) +
expand_limits(x = c(-141, -50), y = c(41, 85))
Note, this course is not making political statements when drawing maps.
m2 <- m1 |> filter(region == "Ukraine")
m2 <- m1 |> filter(region == "Iran")
m2 <- m1 |> filter(region == "Chile")
m2 <- m1 |> filter(region == "Israel")
m2 <- m1 |> filter(region == "Palestine")
m2 <- m1 |> filter(region == "China")
m2 <- m1 |> filter(region == "Taiwan")
m2 <- m1 |> filter(region == "USA")
m2 <- m1 |> filter(region == "USA", subregion == "Hawaii")
m2 <- map_data("usa")
m2 <- m1 |> filter(region == "France")
m2 <- map_data("france") # more detail
ggplot(m2, aes(map_id = region, x = long, y = lat)) +
geom_map(fill = "white", color = "black", size = 0.5, map = m2) +
coord_map("mollweide") +
expand_limits(x = range(m2$long), y = range(m2$lat))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Sometimes it is useful to have a world map centred on the Pacific Ocean.
m2 <- map_data("world2")
ggplot(m2, aes(map_id = region)) +
geom_map(fill = "white", color = "black", size = 0.5, map = m2) +
# coord_map("gilbert")
expand_limits(x = c(0, 360), y = c(-90, 90)) +
coord_map("mollweide")
# coord_map("lambert", -25, 25) # not good for the whole globe
# coord_map("albers", -25, 25)
m2 <- map_data("world")
ggplot(m2, aes(map_id = region)) +
geom_map(fill = "white", color = "black", size = 0.5, map = m2) +
# coord_map("gilbert")
expand_limits(x = c(-180, 180), y = c(-90, 90)) +
coord_map("mollweide")
# coord_map("lambert", -25, 25) # not good for the whole globe
# coord_map("albers", -25, 25)
Get a list of projections from help(“mapproject”) (in
mapproj
package).
You can use a second data frame to add fill colours to a region. This second table must name the regions with the same codes as the map.
values <- tibble( region = m1 |> pull(region) |> unique())
values <- values |> mutate(value = runif(nrow(values)))
map2 <- ggplot(values, aes(map_id = region)) +
geom_map(aes(fill = value),
map = m1,
colour = "white",
alpha = 1, linewidth = 0.2) +
expand_limits(x = c(-180,180), y = c(-80,80)) +
theme_bw() +
coord_map("mollweide")
map2
map2 + theme_void() # removes axes, labels; leaves legend
Show just a few regions
map2 <- ggplot(m1, aes(map_id = region)) +
geom_map(fill = "gray", color = "white", map = m1, linewidth = 0.2) +
geom_map(aes(fill = value),
data = values |> slice_sample(n = 50),
map = m1,
colour = "white", alpha = 1, size=0.2) +
expand_limits(x = c(-180,180), y = c(-80,80)) +
theme_bw() +
coord_map("mollweide")
map2 + theme_void()
Start with some data:
library(maps)
##
## Attaching package: 'maps'
## The following object is masked from 'package:purrr':
##
## map
canada.cities |> head()
## name country.etc pop lat long capital
## 1 Abbotsford BC BC 157795 49.06 -122.30 0
## 2 Acton ON ON 8308 43.63 -80.03 0
## 3 Acton Vale QC QC 5153 45.63 -72.57 0
## 4 Airdrie AB AB 25863 51.30 -114.02 0
## 5 Aklavik NT NT 643 68.22 -135.00 0
## 6 Albanel QC QC 1090 48.87 -72.42 0
Add points to a map:
library(ggrepel)
m2 <- m1 |> filter(region == "Canada")
ggplot(m2) +
geom_map(aes(map_id = region),
fill = "white", color = "black", linewidth = 0.5, map = m2) +
geom_point(data = canada.cities,
aes(x = long, y = lat),
colour = "lightblue", size = 0.25) +
geom_label_repel(data = canada.cities |> filter(pop > 500000),
aes(x = long, y = lat, label = name),
size = 3) +
geom_point(data = canada.cities |> filter(pop > 500000),
aes(x = long, y = lat),
size = 0.75, color = "red") +
coord_map("albers", 60, 90) +
theme_void()