rggplot2gisworld-map

Color countries on world map based on ISO3 codes in R using ggplot()


I wonder whether I can color countries using ggplot? Using rworldmap this is pretty simple and adding points to lat/long values via ggplot is easy as well.

Is there a way of coloring countries based on a simple table using ggplot (country names in ISO3 and a number for each country?) The coloring should be based on the count.

p <- ggplot(legend=FALSE) +

geom_polygon(fill = "darkseagreen", data=world, aes(x=long, y=lat,group=group)) + 
 geom_path(colour = "grey40") + 
 theme(panel.background = element_rect(fill = "lightsteelblue2", colour = "grey")) +
 theme(panel.grid.major = element_line(colour = "grey90")
) +
 theme(panel.grid.minor = element_blank()) +
 theme(axis.text.x = element_blank(),
 axis.text.y = element_blank()) +
 theme(axis.ticks = element_blank()) +
 xlab("") + ylab("")

Solution

  • It's pretty straightforward with ggplot. In the following I use a GeoJSON version of the Natural Earth country boundaries (which stores the ISO3 code in iso_a3) projected to Winkel-Tripel. I stored a CSV of World Bank population data in a gist and read that in for the simple table. I then build two layers, one base layer for the world geometries then the filled-in polygons. Since it's pre-projected, I use coord_equal vs coord_map (which is fine for choropleths but not so much if you intend to draw lines as you'll need to pre-project them, then, too):

    library(maptools)
    library(mapproj)
    library(rgeos)
    library(rgdal)
    library(ggplot2)
    library(jsonlite)
    library(RCurl)
    
    # naturalearth world map geojson
    URL <- "https://github.com/nvkelso/natural-earth-vector/raw/master/geojson/ne_50m_admin_0_countries.geojson.gz"
    fil <- basename(URL)
    
    if (!file.exists(fil)) download.file(URL, fil)
    R.utils::gunzip(fil)
    world <- readOGR(dsn="ne_50m_admin_0_countries.geojson", layer="OGRGeoJSON")
    
    # remove antarctica
    world <- world[!world$iso_a3 %in% c("ATA"),]
    
    world <- spTransform(world, CRS("+proj=wintri"))
    
    dat_url <- getURL("https://gist.githubusercontent.com/hrbrmstr/7a0ddc5c0bb986314af3/raw/6a07913aded24c611a468d951af3ab3488c5b702/pop.csv")
    pop <- read.csv(text=dat_url, stringsAsFactors=FALSE, header=TRUE)
    
    map <- fortify(world, region="iso_a3")
    
    # data frame of markers 
    labs <- data.frame(lat=c(39.5, 35.50), 
                       lon=c(-98.35, 103.27), 
                       title=c("US", "China"))
    
    # pre-project them to winkel-tripel
    coordinates(labs) <-  ~lon+lat
    c_labs <- as.data.frame(SpatialPointsDataFrame(spTransform(
      SpatialPoints(labs, CRS("+proj=longlat")), CRS("+proj=wintri")),
      labs@data))
    
    gg <- ggplot()
    gg <- gg + geom_map(data=map, map=map,
                        aes(x=long, y=lat, map_id=id, group=group),
                        fill="#ffffff", color=NA)
    gg <- gg + geom_map(data=pop, map=map, color="white", size=0.15,
                        aes(fill=log(X2013), group=Country.Code, map_id=Country.Code))
    gg <- gg + geom_point(data=c_labs, aes(x=lon, y=lat), size=4)
    gg <- gg + scale_fill_gradient(low="#f7fcb9", high="#31a354", name="Population by Country\n(2013, log scale)")
    gg <- gg + labs(title="2013 Population")
    gg <- gg + coord_equal(ratio=1)
    gg <- gg + ggthemes::theme_map()
    gg <- gg + theme(legend.position="bottom")
    gg <- gg + theme(legend.key = element_blank())
    gg <- gg + theme(plot.title=element_text(size=16))
    gg
    

    enter image description here