Search code examples
rggplot2ggmap

Adding geom_point to ggmap (ggplot2)


Assume the following minimal data set.

ddf <- structure(list(Country = c("Afghanistan", "Albania", "Algeria", "Angola", "Argentina", "Armenia"), 
x1 = c(16L, 7L, 2L, 1L, 11L, 4L), x2 = c(1150.36, 9506.12, 7534.06, 6247.28, 18749.34, 6190.75)), 
.Names = c("Country", "x1", "x2"), row.names = c(1L, 3L, 4L, 5L, 6L, 7L), class = "data.frame", 
na.action = structure(2L, .Names = "2", class = "omit"))

I borrowed code from this post to generate the initial map. I am assigning color to the countries based on the x1 variable as follows:

library(RColorBrewer)
library(maptools)
library(ggplot2)
data(wrld_simpl)
wrld_simpl@data$id <- wrld_simpl@data$NAME
wrld <- fortify(wrld_simpl, region="id")
wrld <- subset(wrld, id != "Antarctica") # we don't rly need Antarctica
gg <- ggplot()
gg <- gg + geom_map(data=wrld, map=wrld, aes(map_id=id, x=long, y=lat), fill="white", color="#7f7f7f", size=0.25)
gg <- gg + geom_map(data=ddf, map=wrld, aes(map_id=Country, fill=x1),  color="white", size=0.25) 

I want to add geom_point to each one of these countries, and set the size of the geom equal to my x2 variable. I'm not quite sure how this is done. My thinking has been guided by this post, but so far no luck. Any assistance would be greatly appreciated!


Solution

  • You need a set of coordinates - the centres or centroids for each country. wrld contains long and lat for the boundaries (polygons) for each country. A simple method for calculating centroids is to take the mean of the range of the long and lat values for each country.

    ddf <- structure(list(Country = c("Afghanistan", "Albania", "Algeria", "Angola", "Argentina", "Armenia"), 
    x1 = c(16L, 7L, 2L, 1L, 11L, 4L), x2 = c(1150.36, 9506.12, 7534.06, 6247.28, 18749.34, 6190.75)), 
    .Names = c("Country", "x1", "x2"), row.names = c(1L, 3L, 4L, 5L, 6L, 7L), class = "data.frame", 
    na.action = structure(2L, .Names = "2", class = "omit"))
    
    library(RColorBrewer)
    library(maptools)
    library(ggplot2)
    
    data(wrld_simpl)
    wrld_simpl@data$id <- wrld_simpl@data$NAME
    wrld <- fortify(wrld_simpl, region="id")
    wrld <- subset(wrld, id != "Antarctica") # we don't rly need Antarctica
    
    # Select the countries
    SelectedCountries = subset(wrld, id %in% c("Afghanistan", "Albania", "Algeria", "Angola", "Argentina", "Armenia"))
    
    # Get their centres
    CountryCenters <- aggregate(cbind(long, lat) ~ id, data = SelectedCountries, 
                        FUN = function(x) mean(range(x)))
    
    # Merge with the DDf data frame
    ddf = merge(ddf, CountryCenters, by.x = "Country", by.y = "id")
    
    gg <- ggplot() +
       geom_map(data=wrld, map=wrld, aes(map_id=id, x=long, y=lat), fill="white", color="#7f7f7f", size=0.25) +
       geom_map(data=ddf, map=wrld, aes(map_id=Country, fill = x1), size=0.25) +
       geom_point(data=ddf, aes(x=long, y=lat, size = x2), colour = "red")     # plot the points
    

    For better centring, you can use the Polygon function from the sp package, as demonstrated here: stackoverflow.com/.../improve-centering-county-names-ggplot-maps. It gets Argentina wrong, but I think it is something to do with islands. In wrld, I think piece==1 selects the mainland, but it might not work for all countries.

    ddf <- structure(list(Country = c("Afghanistan", "Albania", "Algeria", "Angola", "Argentina", "Armenia"), 
    x1 = c(16L, 7L, 2L, 1L, 11L, 4L), x2 = c(1150.36, 9506.12, 7534.06, 6247.28, 18749.34, 6190.75)), 
    .Names = c("Country", "x1", "x2"), row.names = c(1L, 3L, 4L, 5L, 6L, 7L), class = "data.frame", 
    na.action = structure(2L, .Names = "2", class = "omit"))
    
    library(RColorBrewer)
    library(maptools)
    library(ggplot2)
    
    data(wrld_simpl)
    wrld_simpl@data$id <- wrld_simpl@data$NAME
    wrld <- fortify(wrld_simpl, region="id")
    wrld <- subset(wrld, id != "Antarctica") # we don't rly need Antarctica
    
    # Select the countries
    SelectedCountries = subset(wrld, id %in% c("Afghanistan", "Albania", "Algeria", "Angola", "Argentina", "Armenia"))
    
    
    # Function to calculate centroids
    GetCentroidPoint <- function(SelectedCountries) {Polygon(SelectedCountries[c('long', 'lat')])@labpt}
    
    # Apply the function to the selected countries
    centroids = by(subset(SelectedCountries, piece == 1), factor(subset(SelectedCountries, piece == 1)$id), GetCentroidPoint) 
    
    # Convert list to data frame
    centroids <- do.call("rbind.data.frame", centroids)  
    names(centroids) <- c('long', 'lat') 
    centroids$Country = row.names(centroids)
    
    # Merge with DDF
    ddf = merge(ddf, centroids, by = 'Country')
    
    
    gg <- ggplot() +
       geom_map(data=wrld, map=wrld, aes(map_id=id, x=long, y=lat), fill="white", color="#7f7f7f", size=0.25) +
       geom_map(data=ddf, map=wrld, aes(map_id=Country, fill = x1), size=0.25) +
       geom_point(data=ddf, aes(x=long, y=lat, size = x2), colour = "red")
    

    enter image description here