Gregor Gregor - 2 months ago 35
R Question

When should I use geom_map?

I'm making a choropleth map with added points in ggplot.
So, following the last example of the geom_map help docs

I came up with this:

require(ggplot2)
require(maps)

set.seed(47)
county_map <- map_data("county", "washington")
names(county_map)[5:6] <- c("state", "id")
countyData <- data.frame(id = unique(county_map$id), value = rnorm(39))
map1 <- ggplot(countyData, aes(map_id = id)) +
geom_map(aes(fill = value), map = county_map, colour = "black") +
coord_map() +
expand_limits(x = county_map$long, y = county_map$lat)

print(map1)


which works great for the choropleth map. (Aside that I'm thrilled with the
map_data
function.) But then I try and add points

pointData <- structure(list(xx = c(-119.872483243387, -122.809038239929,
-122.143143065312
), yy = c(48.1320425447619, 46.7352071436801, 47.9911548514037
)), .Names = c("xx", "yy"), row.names = c(1746L, 7281L, 2692L
), class = "data.frame")

map1 + geom_point(mapping = aes(xx, yy), data = pointData)


And I can't get it to work. I tried a lot of variations, setting
group
to
NULL
, naming
aes
arguments, etc. No luck. So I find this question which does the exact same thing without a problem by merging the map data with the choropleth data and using
geom_polygon
, which seems more straightforward anyway. (It took me a little while to work out the ID mapping in the first place because I didn't realize I had to remove the
region
column name to successfully use
id
. And the syntax of the first method still seems weird to me.)

So, two questions:


  1. How is it possible to add points from a different data frame using the method shown above with
    geom_map
    ?

  2. More importantly, are there any advantages to using
    geom_map
    as opposed to the
    geom_polygon
    approach?


Answer Source

Your immediate problem is that ggplot has no way to tie your point data to the map. Looking at your data frames, you have this for your map:

str(countyData)
'data.frame':   39 obs. of  2 variables:
 $ id   : chr  "adams" "asotin" "benton" "chelan" ...
 $ value: num  1.995 0.711 0.185 -0.282 0.109 ...

...and this for your points:

str(pointData)
'data.frame':   3 obs. of  2 variables:
 $ xx: num  -120 -123 -122
 $ yy: num  48.1 46.7 48

Do you see any common variables there that would allow ggplot to locate your points?

Still, the problem is easily resolved. I typically use geom_polygon rather than geom_map but that's largely out of habit. This works, for example:

colnames(pointData) <- c('long','lat') # makes consistent with county_map
pointData$group <- 1 # ggplot needs a group to work with
county_map$value <- sapply(1:nrow(county_map),
                           function(x) round(runif(1, 1, 8), 0)) # for colours

ggplot(county_map, aes(x = long, y = lat, group = group)) +
    geom_polygon(aes(fill = value)) +
    coord_map() +
    geom_point(data = pointData, aes(x = long, y = lat), shape = 21, fill = "red")

Which gives the following (note the points). screenshot

However, as to whether you should use geom_map or geom_polygon, I have not really thought about the issue much. Maybe somebody else has a view.