Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

understanding ggplot2 geom_map map_id

Tags:

r

ggplot2

This comes from the ggplot2 documentation:

# Better example
crimes <- data.frame(state = tolower(rownames(USArrests)), USArrests)
library(reshape2) # for melt
crimesm <- melt(crimes, id = 1)
if (require(maps)) {
  states_map <- map_data("state")
  ggplot(crimes, aes(map_id = state)) + geom_map(aes(fill = Murder), map = states_map) + expand_limits(x = states_map$long, y = states_map$lat)
  last_plot() + coord_map()
  ggplot(crimesm, aes(map_id = state)) + geom_map(aes(fill = value), map = states_map) + expand_limits(x = states_map$long, y = states_map$lat) + facet_wrap( ~ variable)
}

I don't understand how this can work since there is no common identifier in the states_map data frame which uses "region" to name the states column and the crimes data frame which labels the states, "states." What ties the data to the map?

In this example the poster renames the columns of the map data frame to conform with the data but the ggplot2 documentation doesn't seem to do it. How? When I rename the columns of states_map in the example above, so that "state" is common to both data frames, it breaks the code.

crimes <- data.frame(state = tolower(rownames(USArrests)), USArrests)
library(reshape2) # for melt
crimesm <- melt(crimes, id = 1)
if (require(maps)) {
  states_map <- map_data("state")
##### my attempt to fix what isn't broken #################
names(states_map)[5]<-"state"
###########################################################
  ggplot(crimes, aes(map_id = state)) + geom_map(aes(fill = Murder), map = states_map) + expand_limits(x = states_map$long, y = states_map$lat)
  last_plot() + coord_map()
 # Error: all(c("x", "y", "id") %in% names(map)) is not TRUE
}

Thanks.

like image 461
Art Avatar asked Jul 14 '15 15:07

Art


1 Answers

If you look up the code for geom_map:

function (mapping = NULL, data = NULL, stat = "identity", ..., 
    map, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) 
{
    stopifnot(is.data.frame(map))
    if (!is.null(map$lat)) 
        map$y <- map$lat
    if (!is.null(map$long)) 
        map$x <- map$long
    if (!is.null(map$region)) 
        map$id <- map$region
    stopifnot(all(c("x", "y", "id") %in% names(map)))

# etcetera...
}

This means, that for the correct building of the geom, a data frame map will be generated with x, y, and id column. With aes(map_id = state) you are basically assigning crimes$state to map$id (to my understanding)

If you don't have an id column in your map data, the column which is called region will be used as your id column. You can test this with changing the name of states_map$region to states_map$id

names(states_map)[5]<-"id" 

This works with the given example.

like image 174
tjebo Avatar answered Oct 27 '22 22:10

tjebo