“The art or technique of making maps”
This link provides a walk through of making dot density maps from census data
tidycensus
package is used to download population data from the US Census Bureau
tigris
package is used to download shapefiles from the US Census and load them into R as sf
objects Here is a helpful guide if you are interested in learning more about the tigris
package.
Examples of available datasets
Function | Datasets available | Years available |
---|---|---|
nation() |
cartographic (1:5m; 1:20m) | 2013-2019 |
divisions() |
cartographic (1:500k; 1:5m; 1:20m) | 2013-2019 |
regions() |
cartographic (1:500k; 1:5m; 1:20m) | 2013-2019 |
states() |
TIGER/Line; cartographic (1:500k; 1:5m; 1:20m) | 1990, 2000, 2010-2019 |
counties() |
TIGER/Line; cartographic (1:500k; 1:5m; 1:20m) | 1990, 2000, 2010-2019 |
tracts() |
TIGER/Line; cartographic (1:500k) | 1990, 2000, 2010-2019 |
block_groups() |
TIGER/Line; cartographic (1:500k) | 1990, 2000, 2010-2019 |
blocks() |
TIGER/Line | 2000, 2010-2019 |
places() |
TIGER/Line; cartographic (1:500k) | 2011-2019 |
pumas() |
TIGER/Line; cartographic (1:500k) | 2012-2019 |
school_districts() |
TIGER/Line; cartographic | 2011-2019 |
zctas() |
TIGER/Line; cartographic (1:500k) | 2000, 2010, 2012-2019 |
congressional_districts() |
TIGER/Line; cartographic (1:500k; 1:5m; 1:20m) | 2011-2019 |
state_legislative_districts() |
TIGER/Line; cartographic (1:500k) | 2011-2019 |
voting_districts() |
TIGER/Line | 2012 |
area_water() |
TIGER/Line | 2011-2019 |
linear_water() |
TIGER/Line | 2011-2019 |
ggplot() +
geom_sf(data = rva, fill = "white", lwd = 1) +
geom_sf(data = water, fill = "lightblue", colour = "lightblue") +
geom_sf(data = roads, colour = "grey") +
geom_sf(data = points, #the creation of the points data is shown in a chunk not included in the published document, but is included if you download this markdown file
aes(colour = education,
fill = education),
size = .5) +
scale_color_brewer(type = "div", palette = 4,
name = "Education") +
scale_fill_brewer(type = "div", palette = 4) +
theme_minimal() +
ggtitle("Distribution of educational attainment in Richmond, Virginia (2019)",
"1 dot equals 10 people") +
guides(fill = "none")
For this example I again used data from tidycensus
and tigris
. The code for processing this data is availble in the markdown document
Note that the circles are plotted as points, not polygons. Proportionate circle sizes are made using aes(size = data$attribute)
#proportionate circle sizes are made
ggplot() +
geom_sf(data = counties, fill = "lightblue", color = "lightblue") +
geom_sf(data = acs, fill = "grey95") +
geom_sf(data = points, aes(size = estimate), color = "lightsalmon2") + #data processing for the points data is shown in the previous chunk (visible in the markdown document). Points are created using centroids of county polygons
theme_minimal() +
ggtitle("Population of Virginia Counties",
"2019") +
labs( size = "Population") +
scale_size_continuous(labels = comma)
For this example I again used data from tidycensus
and tigris
. The code for processing this data is availble in the markdown document
The scaling of color is made by aes(fill = data$attribute)
Choropleth
The package ggisobands
can be used to plot isobands into ggplot2
. x, y, and z values are required in aes()
The scaled colors are achieved in aes(fill =)
In this example the starting data is a Digital Elevation Model (DEM) raster of Downtown Richmond. geom_isobands
creates isobands from point data, so we must convert our raster to points and then put them in a data frame. After that, they’re ready to go!
library(ggisoband)
DEM_5m <- raster("C:/Users/Charis/Documents/Spring2021/GISinR/GISinR/DEM_5m.tif")
DEM_pts <- rasterToPoints(DEM_5m, spatial = TRUE) #I transformed my raster data into a data frame of points, each with an x, y, and z column (z being elevation)
DEM_df <- data.frame(DEM_pts)
DEM_df$DEM_5m <- ifelse(DEM_df$DEM_5m <0, 0, DEM_df$DEM_5m) #There was a section with very negative numbers that I assumed to be a defect in the data, so I made any negative values 0 to clean it up
ggplot(DEM_df, aes(x=x, y=y, z=DEM_5m)) + #You need an x, y, and z in the aes()
geom_isobands(aes(fill = stat(zmin)), color = NA) + #the stat function is used to tell ggplot that you want it to use a calculated aesthetic produced by the statistic
scale_fill_viridis_c()
]
There is a package, isoband
that generates contour lines that can be used with grid.path()
or grid.polyline()
from the grid
library. To use this data in ggplot it must be converted to an sf
object. A vignette of that package is available here.
Robin Lovelace explain spatial vectorization and shows how to use the rasterToContour()
function
Here is the same map using color=
instead of fill=
This is what we started working through during class. The data is from the rnaturalearth
library
note - returnclass
default is sp
world <- ne_countries(scale = "medium", returnclass = "sf")
class(world)
[1] "sf" "data.frame"
world <- world %>%
select(income_grp, subregion, name, name_long, name_alt, pop_est, level, subunit, type, economy)
This is a plain old ggplot, no bells or whistles
ggplot(world) +
geom_sf() -> p
p
Title is added using ggtitle()
Subtitle is added using subtitle =
within the ggtitle()
function axis labels are added with xlab
and ylab
p +
xlab("Longitude") +
ylab("Latitude") +
ggtitle("World Map",
subtitle = paste0("(" ,length(unique(world$name)), "countries)" )) -> p #note that I'm using the `paste0()` function to insert information from my data into my subtitle
p
NA
NA
Custom palette
You can design your own custom palette using hex codes or the assigned color names built into R
my_colors <- c("#999999", "#E69F00", "#56B4E9", "#009E73",
"#F0E442", "#0072B2", "#D55E00")
ggplot(world) +
geom_sf(aes(fill = economy))+
scale_fill_manual(values = my_colors)
It may be helpful to use a website like coolors to choose colors for your palette
Built-it color palettes
There are many packages with pre-defined colors and palettes
viridis
RColorBrewer
Into Wes Anderson’s color schemes? There’s a library for that
wesanderson
I chose the viridis_c
palette
trans =
transformation of data, in this case square root
option =
different color palettes: A-E, default is D
Let’s switch over to the all-too-familiar beetle dataset
beetle_url <- "https://raw.githubusercontent.com/dyerlab/ENVS-Lectures/master/data/Araptus_Disperal_Bias.csv"
read_csv(beetle_url) %>%
st_as_sf( coords=c("Longitude","Latitude"), crs=4326 ) %>% #transform to sf
st_union() %>%
st_buffer(dist = 1) %>%
st_bbox() -> bounds #will use bounds to crop our world data to the beetle area
read_csv(beetle_url) %>%
st_as_sf(coords=c("Longitude","Latitude"), crs = 4326) -> beetle
ggplot(world) +
geom_sf() +
xlab("Longitude") +
ylab("Latitude") + #note that the xlim and ylim values are from `bounds`
ggtitle("Beetles") +
coord_sf( xlim = c(-116, -108), ylim = c(22, 31), expand = FALSE) -> b
b
The result is the world dataset cropped to the bettle dataset
Both the scale bar and north arrow come from package ggspatial
library(ggspatial)
b+
annotation_scale(location = "br", style = "bar") +
annotation_north_arrow(location = "br", width = unit(.5, "cm"),
height = unit(.75, "cm"),
pad_y = unit(0.75, "cm"),
pad_x = unit(0.5, "cm"),
style = north_arrow_orienteering(
text_size = 8
)) -> b
b
changed extent to see more countries
Side-by-Side
library(cowplot)
plot_grid(world_map, Mexico, nrow = 1, rel_widths = c(2.3, 1)) -> p
p
Inset Map
ggplot() +
geom_sf(data = counties, fill = "lightblue", color = "lightblue") +
geom_sf(data = acs, fill = "grey") +
theme_minimal() -> VA_map
VA_map
ggplot() +
geom_sf(data = rva, fill = "grey95", lwd = 1) +
geom_sf(data = water, fill = "lightblue", colour = "lightblue") +
geom_sf(data = roads, colour = "grey")+
annotate("text", x = -77.57, y = 37.62, label= "Richmond", size = 3) +
theme_void() +
coord_sf(datum = NA) -> RVA_map
RVA_map
st_bbox(counties)
xmin ymin xmax ymax
-83.67539 36.54085 -75.16643 39.46601
st_bbox(rva)
xmin ymin xmax ymax
-77.60117 37.44655 -77.38551 37.60281
ggdraw(VA_map) +
draw_plot(RVA_map,
width = 0.25, height = 0.25* 5/2,
x = .15, y = .35) -> p
p
Adding arrows
arrowA <- data.frame(x1 = 18, x2 = 25, y1 = 3.45, y2 = 3.55)
ggplot() +
geom_sf(data = rva, fill = "grey95", lwd = 1) +
geom_sf(data = water, fill = "lightblue", colour = "lightblue") +
geom_sf(data = roads, colour = "grey")+
annotate("text", x = -77.575, y = 37.62, label= "Richmond", size = 3)+
theme_void() +
theme(panel.grid.major = element_line(colour = gray(0.5), linetype = "dashed",
size = 0.5), panel.background = element_rect(fill = "white"),
panel.border = element_rect(fill = NA)) +
coord_sf(datum = NA) -> RVA_map
ggdraw(xlim = c(0, 35), ylim = c(0, 7.5)) +
draw_plot(VA_map, x = 0, y = 0, width = 25, height = 7.5) +
draw_plot(RVA_map, x = 24, y = .5, width = 10, height = 7)+
geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2), data = arrowA,
arrow = arrow(), lineend = "round") -> arrow_box
arrow_box