rtextrworldmap

Avoid overlapping text labels with rworldmap


I am creating a world map with rworldmap and adding the country names using the text function. However, the text labels overlap. I tried the adj and pos parameters, but with no luck thus far. Any tips?

library(rworldmap)

DF = data.frame(q = c("VAT","ESP","CAN","AND","MCO","VCT",
                      "NLD", "LUX", "GBR", "LIE", "BEL", "DNK",
                      "SWE","NOR","ATG","AUS", "BHS", "BHR","BRB",
                      "BLZ","BTN","BRN","KHM","CAN","SWZ","GRD",
                      "JAM","JPN","KWT","JOR","LSO","MYS","MAR",
                      "NZL","OMN","PNG","QAT","KNA","LCA","SAU",
                      "SLB","THA","TON","TUV","ARE" ), 
                Assignment = ("Monarchies Worldwide"))

country = c("Vatican","Spain","Monaco","Canada","Andorra","Saint Vincent and the Grenadines",
            "Netherlands", "Luxembourg","United Kingdom", "Liechtenstein","Belgium","Denmark",
            "Sweden","Norway","Anitgua and Barbuda","Australia", "Bahamas", "Bahrain","Brunei Darussalam",
            "Belize","Bhutan","Cambodia","Swaziland","Grenada","Jamaica","Japan","Kuwait","Jordan",
            "Lesotho","Malaysia","Morocco","New Zealand","Oman","Papua New Guinea","Qatar","Saint Kitts and Nevis",
            "Saint Lucia","Saudi Arabia","Solomon Islands","Thailand","Tonga","Tuvalu","United Arab Emirates")

Map = joinCountryData2Map(DF, 
                          joinCode = "ISO3", 
                          nameJoinColumn ="q", 
                          mapResolution = "coarse") 

mapParams = mapCountryData(Map, 
                           nameColumnToPlot = "Assignment", 
                           catMethod = "categorical",
                           missingCountryCol = gray(.4))

country_coord <- data.frame(coordinates(Map))[country, ]

text(x = country_coord$X1, 
     y = country_coord$X2, 
     labels = row.names(country_coord), 
     adj = NULL, pos = 3,  offset = 0, vfont = NULL,
     cex = 0.3, col = "blue", font = 5)

Solution

  • Answer

    The base text function does not have this functionality. You'll likely have to rely on additional packages to achieve what you want:


    1. basicPlotteR::addTextLabels

    Given some settings, it will displace the text, and use lines to indicate to which country the text belongs.

    # remotes::install_github("JosephCrispell/basicPlotteR")
    library(basicPlotteR)
    
    # replace text() with this
    addTextLabels(x = country_coord$X1, y = country_coord$X2, labels = row.names(country_coord), cex.label = 0.3, col.label = "blue")
    

    enter image description here


    2. ggrepel::geom_text_repel

    This will do the same thing, but with more customization options. Note that geom_text_repel (and geom_label_repel) will remove labels if they cannot be plotted within your requirements.

    library(ggplot2)
    library(ggrepel)
    
    mymap <- fortify(Map)
    mymap$monarch <- mymap$id %in% country
    
    ggplot(data = mymap, aes(x = long, y = lat)) + 
      theme_void() +
      geom_map(map = mymap,
               aes(group = group, map_id = id,
                   fill = monarch),
               color = "#ffffff") +
      scale_fill_manual(values = c("#666666", "#FF0000")) +
      ggrepel::geom_text_repel(data = country_coord, 
                               aes(x = X1, y = X2), 
                               label = row.names(country_coord),
                               size = 2,
                               col = "blue")
    

    enter image description here


    3. ggrepel::geom_label_repel

    This will function like geom_text_repel (also in removing labels that cannot fit the requirements), but the text will have a nice box around it.

    ggplot(data = mymap, aes(x = long, y = lat)) + 
      theme_void() +
      geom_map(map = mymap,
               aes(group = group, map_id = id,
                   fill = monarch),
               color = "#ffffff") +
      scale_fill_manual(values = c("#666666", "#FF0000")) +
      ggrepel::geom_label_repel(data = country_coord, 
                               aes(x = X1, y = X2), 
                               label = row.names(country_coord),
                               size = 2,
                               col = "blue")
    

    enter image description here