You can use coordinates, namely longitude and latitude, to add features like segments and points to your maps
It is useful to know how to compute the centroid of a polygon
Now that we know how to deal with colors we can go back to our Yaounde map because we can still improve our visualization. Indeed, when we have several regions, the above visualization might get confusing. To simplify the visualization we can add the labels on each region with geom_sf_label() and remove the legend with legend.position = FALSE.
library(dplyr)
library(sf)
library(here)
library(ggplot2)
<-
yaounde_map read_sf(here("chapter_06_basic_maps/data/yaounde_map.shp"))
ggplot(yaounde_map) +
geom_sf(aes(fill = region)) +
coord_sf(datum = NA)+
geom_sf_label(aes(label = region), label.padding = unit(1,"mm"))+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())
Alternatively, we can remove the labels white background using geom_sf_text(aes(label = NAME)).
ggplot(yaounde_map) +
geom_sf(aes(fill = region)) +
coord_sf(datum = NA)+
geom_sf_text(aes(label = region), size = 3, color = "black", fontface = "bold")+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())
Now, we would like to avoid that some labels overlap like Ekoudou and Briqueterie. To do that we can create a dataframe defining our new parameters for the Latitude and longitude. Note that if you need to make it from scratch you may need to try different solutions and turn off the datum = NA from coord_sf() to see the coordinates might be useful.
Here below we can define the new positions parameters for our labels.
#first, we define a column with our region names
<- c("Messa",
region "Mokolo",
"Cité Verte",
"Ekoudou",
"Briqueterie",
"Nkomkana",
"Carriere",
"Tsinga",
"Tsinga Oliga")
#here we define the new longitude value
<- c(11.51000,
longitude_adjusted 11.49703,
11.48400,
11.50900,
11.51700,
11.49594,
11.48600,
11.50900,
11.48530)
#here we define the new latitude value
<- c(3.870000,
latitude_adjusted 3.875733,
3.875000,
3.886500,
3.877396,
3.883400,
3.888508,
3.892000,
3.903376)
#now we can merge the arrays in a single dataframe
<- data.frame(region, longitude_adjusted, latitude_adjusted) region_centroids
Now we can use the newly created dataframe to define the positions of the labels. Note, that here below we don’t use geom_sf_text() because it requires a geometry column that is not present in region_centroids. and we can simply use geom_text(). Also, we need to increase the x-axis limits in order to plot the entire Briqueterie label using scale_x_continuous(limits = c()).
ggplot(yaounde_map) +
geom_sf(aes(fill = region)) +
coord_sf(datum = NA)+
geom_text(data = region_centroids,
aes(longitude_adjusted, latitude_adjusted, label = region), size = 3, color = "black", fontface = "bold")+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())+
scale_x_continuous(limits = c(11.46, 11.525))
As we can see the labels are not overlapping anymore. However, looking at our map we cannot define the location of Tsinga and Ekodou. A trick that we can adopt is to draw a segment to connect those labels to the proper region. One way to make it is to find the original centroids (the center point of the object) of each region. This process is very simple since the sf library provides the st_centroid() function that we can use to call our map geometry and compute the centroids.
<- st_centroid(yaounde_map$geometry)
centroids
#with st_centroid we create a list. For us is simpler to convert it to a dataframe
<- data.frame(matrix(unlist(centroids), nrow=length(centroids), byrow=TRUE))
centroids
#rename the variables
<-centroids %>%
centroids rename(longitude = X1,
latitude = X2)
centroids
## longitude latitude
## 1 11.50885 3.871741
## 2 11.49672 3.875731
## 3 11.48775 3.876026
## 4 11.50479 3.877702
## 5 11.51060 3.877517
## 6 11.49586 3.883364
## 7 11.48834 3.885330
## 8 11.50325 3.886581
## 9 11.48519 3.904435
Now we can add the original centroids to the region_centroids dataframe previously created.
<- data.frame(region_centroids, centroids) region_centroids
The two regions that need a segment are “Tsinga” and “Ekoudou”. One way to do this is to first create a column in region_centroids to indicate if a region needs a segment using an ifelse statement.
$segment <- ifelse(region_centroids$region == "Tsinga" |region_centroids$region == "Ekoudou","yes", NA) region_centroids
Finally, we can plot the segments using geom_segment().
ggplot(yaounde_map) +
geom_sf(aes(fill = region)) +
coord_sf(datum = NA)+
geom_text(data = region_centroids,
aes(longitude_adjusted, latitude_adjusted, label = region), size = 3, color = "black", fontface = "bold")+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())+
scale_x_continuous(limits = c(11.46, 11.525))+
geom_segment(data = subset(region_centroids, segment == "yes") ,
aes(longitude, latitude, xend = longitude_adjusted, yend = latitude_adjusted - 0.001), color = "black")
One last feature that we may consider adding to our maps is some dots. The process is the same that we just saw for the segments i.e. is sufficient to create a dataframe with the longitude and latitude of our points and add it to the map using geom_point() function.
Let’s try an example starting from our last map. In this example, we want to add a point where the label segments are pointing. We first prepare the dataframe
#we use again the ifelse statement to create a "point" variable
$point <- ifelse(region_centroids$region == "Tsinga" |region_centroids$region == "Ekoudou","yes", NA) region_centroids
Now we can add geom_point()
ggplot(yaounde_map) +
geom_sf(aes(fill = region)) +
coord_sf(datum = NA)+
geom_text(data = region_centroids,
aes(longitude_adjusted, latitude_adjusted, label = region), size = 3, color = "black", fontface = "bold")+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())+
scale_x_continuous(limits = c(11.46, 11.525))+
geom_segment(data = subset(region_centroids, segment == "yes") ,
aes(longitude, latitude, xend = longitude_adjusted, yend = latitude_adjusted - 0.001), color = "black")+
geom_point(data = subset(region_centroids, segment == "yes"),
aes(longitude, latitude), colour = "black")
Another way to use geom_point() is to indicate the position of a relevant spot. For instance, let’s add a point where is located the School in Tsinga Oliga (École Publique)
#prepare the data
<- "School"
name <- 11.49633 #coordinates source: openstreetmap.org
longitude_school <- 3.89247
latitude_school
<- data.frame(name, longitude_school, latitude_school) school
ggplot(yaounde_map) +
geom_sf(aes(fill = region)) +
coord_sf(datum = NA)+
geom_text(data = region_centroids,
aes(longitude_adjusted, latitude_adjusted, label = region), size = 3, color = "black", fontface = "bold")+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())+
scale_x_continuous(limits = c(11.46, 11.525))+
geom_segment(data = subset(region_centroids, segment == "yes") ,
aes(longitude, latitude, xend = longitude_adjusted, yend = latitude_adjusted - 0.001), color = "black")+
geom_point(data = subset(region_centroids, segment == "yes"),
aes(longitude, latitude), colour = "black")+
geom_point(data = school, aes(longitude_school, latitude_school),
colour = "blue")+
geom_text(data = school, aes(longitude_school, latitude_school + 0.002,
label = name), size = 3, color = "blue")
________________________________________________________________________________________________________________
To answer the following questions you need to upload the Ghana map (ghana_map.shp) you can find in the exercises folder
::: practice - What is the centroid longitude of Bono East region?
What is the centroid latitude of Volta region?
In which region would a point be located using the following coordinates (7.8813, 0.3214)?
Name all the regions of where the following coordinates are located:
6.742, -2.316
10.391, -1.28
9.2711, -0.791
#Delete the wrong answers
<- "Ashanti, Ahafo, Western North"
q4 <- "Ahafo, Upper East, Savannah"
q4 <- "Volta, Bono East, Bono"
q4 <- "Ahafo, Upprt East, Bono"
q4
.check_q4()
## Wrong. Please try again.
## 1 2 3 4
.hint_q4()
## Try to use geom_point
.score_print()
##
## 1 2 3 4
In the following exercise you can test what learned about labels and coordinates
Import the choropleth map of Ghana
Add the labels from column “ADM1_REF”
You have to change the position of the following labels : Western North, Ahafo, Greater Accra, Northern East. The objective is to place them where there is no overlap with surrounding boundaries (hint: to simplify the task you can use geom_text function for the labels). You are free to move the labels as you prefer, but you need to preserve the map’s Interpretability. Also, all the labels must be fully visible and not truncated
For each of the 4 labels, you must draw a segment connecting it to the centroid of the respective region. The condition is that the label has to be fully readable and the segment does not overlap any letter
Solution:
#import map
<-
ghana_map read_sf(here("chapter_06_basic_maps/data/exercises/ghana_map.shp"))
#extract centroids
<- st_centroid(ghana_map$geometry)
centroids_gha <- data.frame(matrix(unlist(centroids_gha), nrow=length(centroids_gha), byrow=TRUE))
centroids_gha
<-centroids_gha %>%
centroids_gha rename(longitude = X1,
latitude = X2)
#create a dataframe with regions and adjusted/unadjusted centroids
<- c(ghana_map$ADM1_EN)
ghana_regions
<- c(-4.7040655,#changed
longitude_adjusted_gha -1.45724013,
-2.50343566,
-1.07729786,
-1.21521406,
-0.44868913,
0.16833596,#changed
-0.28536495,
1.29333135,#changed
0.27308419,
-1.53193193,
-0.80345890,
-2.21219512,
0.54801960,
-2.14897384,
-3.98820576)#changed
<- c(5.915907,#changed
latitude_adjusted_gha 6.799353,
7.692704,
7.885513,
5.567690,
6.417510,
5.205687,#changed
9.462481,
9.829237,#changed
7.968664,
9.035376,
10.780881,
10.425577,
6.423451,
5.399914,
5.424480)#changed
<-
label_coordinates data.frame(ghana_regions,
centroids_gha,
longitude_adjusted_gha,
latitude_adjusted_gha)
#define segments
$segment <- ifelse(
label_coordinates$ghana_regions == "Western North" |
label_coordinates$ghana_regions == "Ahafo" |
label_coordinates$ghana_regions == "Greater Accra"|
label_coordinates$ghana_regions == "Northern East" ,"yes", NA)
label_coordinates
ggplot(ghana_map) +
geom_sf(aes(fill = ADM1_EN)) +
coord_sf()+
geom_text(data = label_coordinates,
aes(longitude_adjusted_gha, latitude_adjusted_gha, label = ghana_regions), size = 3, color = "black", fontface = "bold")+
theme(panel.background = element_rect(fill = "transparent"),
legend.position = "None",
axis.title.y=element_blank(),
axis.title.x=element_blank())+
geom_segment(data = subset(label_coordinates, segment == "yes") ,
aes(longitude, latitude, xend = longitude_adjusted_gha, yend = latitude_adjusted_gha +0.05), color = "black")+
scale_x_continuous(limits = c(-6, 4))
The following team members contributed to this lesson: