This post was originally published here
This post demonstrates the use of two very cool R packages – ggrepel
and patchwork
.
ggrepel
deals with overlapping text labels (Code#1 at the bottom of this post):

patchwork
is a very convenient new package for combining multiple different plots together (i.e. what we usually to use grid
and gridExtra
for).
More info:
To really demonstrate the power of them, let’s make a global map of country names using ggrepel
:
|
library(tidyverse) library(ggrepel) library(patchwork) # data from https://worldmap.harvard.edu/data/geonode:country_centroids_az8 orig_data = read_csv("country_centroids_az8.csv") centroidsdata = orig_data %>% select(country = admin, continent, lat = Latitude, lon = Longitude) %>% filter(continent != "Seven seas (open ocean)" & continent != "Antarctica") %>% mutate(continent = fct_collapse(continent, "Americas" = c("North America", "South America"))) head(centroidsdata) |
|
## # A tibble: 6 x 4 ## country continent lat lon ## <chr> <fct> <dbl> <dbl> ## 1 Aruba Americas 12.5 -70.0 ## 2 Afghanistan Asia 33.8 66.0 ## 3 Angola Africa -12.3 17.5 ## 4 Anguilla Americas 18.2 -63.1 ## 5 Albania Europe 41.1 20.0 ## 6 Aland Europe 60.2 20.0 |
|
plot1 = centroidsdata %>% ggplot(aes(x = lon, y = lat, label = country, colour = continent)) + geom_text_repel(segment.alpha = 0) + theme_void() + scale_color_brewer(palette = "Dark2") plot1 |

Now this is very good already with hardly any overlapping labels and the world is pretty recognisable. And really, you can make this plot with just 2 lines of code:
|
ggplot(centroidsdata, aes(x = lon, y = lat, label = country)) + geom_text_repel(segment.alpha = 0) |
So what these two lines make is already very amazing.
But I feel like Europe is a little bit misshapen and that the Caribbean and Africa are too close together. So I divided the world into regions (in this case same as continents except Russia is it’s own region – it’s just so big). Then wrote two functions that asked ggrepel
to plot each region separately and use patchwork
to patch each region together:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
centroidsdata = centroidsdata %>% mutate(region = continent %>% fct_expand("Russia")) %>% mutate(region = replace(region, country == "Russia", "Russia")) mapbounds = centroidsdata %>% group_by(region) %>% summarise(xmin = min(lon), xmax = max(lon), ymin = min(lat), ymax = max(lat)) create_labelmap = function(mydata, mycontinent, myforce = 1, mycolour = "black"){ mymapbounds = mapbounds %>% filter(region == mycontinent) mydata %>% filter(region == mycontinent) %>% ggplot(aes(x = lon, y = lat, label = country)) + geom_text_repel(segment.alpha = 0, force = myforce, colour = mycolour) + theme_void() + theme(legend.position = "none") + scale_y_continuous(limits = c(mymapbounds$ymin, mymapbounds$ymax)) + scale_x_continuous(limits = c(mymapbounds$xmin, mymapbounds$xmax)) } mycolours = RColorBrewer::brewer.pal(5,"Dark2") make_world = function(mydata){ mydata = centroidsdata afr = create_labelmap(mydata, "Africa", mycolour = mycolours[1]) ame = create_labelmap(mydata, "Americas", mycolour = mycolours[4]) asi = create_labelmap(mydata, "Asia", mycolour = mycolours[2]) eur = create_labelmap(mydata, "Europe", mycolour = mycolours[3]) rus = create_labelmap(mydata, "Russia", mycolour = mycolours[3]) oce = create_labelmap(mydata, "Oceania", mycolour = mycolours[5]) (ame + (eur / afr) + (rus / asi / oce)) + plot_layout(ncol = 3) } plot2 = make_world(centroidsdata) plot2 |

This gives continents a much better shape, but it does severaly misplace Polynesia. See if you can find where, e.g., Tonga is and where it should be.
To see what I did with patchwork there, let’s add black borders to each region (Code#2):

Code#1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#devtools::install_github("slowkow/ggrepel") #devtools::install_github("thomasp85/patchwork") library(tidyverse) library(ggrepel) library(patchwork) mydata = data_frame(x = c(1, 1.3), y = c(1, 1), mylabel = c("Point-1", "Point-2")) p = mydata %>% ggplot(aes(x, y, label = mylabel, colour = mylabel)) + geom_point() + coord_cartesian(xlim = c(-3, 3), ylim = c(-3, 3)) + theme_bw() + theme(legend.position = "none") + scale_colour_viridis_d() plot1 = p + geom_text() + ggtitle("geom_text()") plot2 = p+ geom_text_repel() + ggtitle("geom_text_repel()") plot1 + plot2 |
Code#2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
create_labelmap = function(mydata, mycontinent, myforce = 1, mycolour = "black"){ mymapbounds = mapbounds %>% filter(region == mycontinent) mydata %>% filter(region == mycontinent) %>% ggplot(aes(x = lon, y = lat, label = country)) + geom_text_repel(segment.alpha = 0, force = myforce, colour = mycolour) + theme_void() + theme(legend.position = "none") + scale_y_continuous(limits = c(mymapbounds$ymin, mymapbounds$ymax)) + scale_x_continuous(limits = c(mymapbounds$xmin, mymapbounds$xmax)) + theme(panel.border = element_rect(colour = "black", fill=NA, size=5)) } plot3 = make_world(centroidsdata) plot3 |