Mapping different states in R using facet wrap

荒凉一梦 提交于 2019-12-19 04:25:47

问题


I am trying to use facet_wrap in ggplot2 to map a different state into each facet of a multi-faceted plot. My code is listed here, where 'dataset' is a data frame containing a variable named 'state', which contains the names of the different states I want mapped by facet.

library(maps)
library(ggplot2)

states <- c('Oklahoma','Arizona','Washington','North     
Dakota','Michigan','Florida')

map <- ggplot(data=datatest) + geom_polygon(data=map_data
('state',region=datatest$state),aes
(x=long,y=lat,group=group),colour='black',fill='white') + 
facet_wrap(~state,ncol=3)

I'm not able to get each facet to be a map of a different state. Instead, each facet is a map of the whole United States with the six listed states appearing on it. If anyone knows of a way to get this to work where each facet is a different state by itself, I would greatly appreciate it. I'm pretty sure it has to do with how the 'region' is defined in the call to map_data, but nothing I've tried is working. It's possible this can't be done, but I thought I'd see if anyone has an idea. Thank you!


回答1:


The column state is not present in the return from map_data. There, the column you are looking for is called region. Further, at least in your example, there is no data being plotted from the datatest data. So, you can omit it.

This code should work. Note that I added scales = "free" because I am assuming that you want each state to fill it's corresponding facet.

ggplot(map_data('state',region=states)
       , aes(x=long,y=lat,group=group)) +
  geom_polygon(colour='black',fill='white') + 
  facet_wrap(~region
             , scales = "free"
             , ncol=3)

Gives

Note that the aspect ratios are going to be off using facet_wrap because the facets can't handle the coord_map controls. To make the plot better, I would suggest making each state map separately and then using plot_grid from cowplot to stitch them together. Note that cowplot loads a default theme, so you will want to either reset your default (with theme_set) or explicitly set a theme for the plots (as I do here):

sepStates <-
  lapply(states, function(thisState){
    ggplot(map_data('state',region=thisState)
           , aes(x=long,y=lat,group=group)) +
      geom_polygon(colour='black',fill='white') +
      facet_wrap(~region) +
      coord_map() +
      theme_void()
  })


library(cowplot)
plot_grid(plotlist = sepStates)

gives

If you want to include data from another source, you will need to make sure that it is compatible. In particular, you need to make sure that the column you want to be facetting based on is called the same thing in both.

Let's imagine you have the following data that you want to add to the plot:

datatest <-
structure(list(zip = c("85246", "85118", "85340", "34958", "33022", 
"32716", "49815", "48069", "48551", "58076", "58213", "58524", 
"73185", "74073", "73148", "98668", "98271", "98290"), city = c("Chandler", 
"Gold Canyon", "Litchfield Park", "Jensen Beach", "Hollywood", 
"Altamonte Springs", "Channing", "Pleasant Ridge", "Flint", "Wahpeton", 
"Ardoch", "Braddock", "Oklahoma City", "Sperry", "Oklahoma City", 
"Vancouver", "Marysville", "Snohomish"), state = c("AZ", "AZ", 
"AZ", "FL", "FL", "FL", "MI", "MI", "MI", "ND", "ND", "ND", "OK", 
"OK", "OK", "WA", "WA", "WA"), latitude = c(33.276539, 33.34, 
33.50835, 27.242402, 26.013368, 28.744752, 46.186913, 42.472235, 
42.978995, 46.271839, 48.204374, 46.596608, 35.551409, 36.306323, 
35.551409, 45.801586, 48.093129, 47.930902), longitude = c(-112.18717, 
-111.42, -112.40523, -80.224613, -80.144217, -81.22328, -88.04546, 
-83.14051, -83.713124, -96.608142, -97.30774, -100.09497, -97.407537, 
-96.02081, -97.407537, -122.520347, -122.21614, -122.03976)), .Names = c("zip", 
"city", "state", "latitude", "longitude"), row.names = c(NA, 
-18L), class = c("tbl_df", "tbl", "data.frame"))

which looks like this:

     zip              city state latitude  longitude
   <chr>             <chr> <chr>    <dbl>      <dbl>
 1 85246          Chandler    AZ 33.27654 -112.18717
 2 85118       Gold Canyon    AZ 33.34000 -111.42000
 3 85340   Litchfield Park    AZ 33.50835 -112.40523
 4 34958      Jensen Beach    FL 27.24240  -80.22461
 5 33022         Hollywood    FL 26.01337  -80.14422
 6 32716 Altamonte Springs    FL 28.74475  -81.22328
 7 49815          Channing    MI 46.18691  -88.04546
 8 48069    Pleasant Ridge    MI 42.47223  -83.14051
 9 48551             Flint    MI 42.97899  -83.71312
10 58076          Wahpeton    ND 46.27184  -96.60814
11 58213            Ardoch    ND 48.20437  -97.30774
12 58524          Braddock    ND 46.59661 -100.09497
13 73185     Oklahoma City    OK 35.55141  -97.40754
14 74073            Sperry    OK 36.30632  -96.02081
15 73148     Oklahoma City    OK 35.55141  -97.40754
16 98668         Vancouver    WA 45.80159 -122.52035
17 98271        Marysville    WA 48.09313 -122.21614
18 98290         Snohomish    WA 47.93090 -122.03976

If you want to facet on the state, you need to make it into the same format (i.e., full name and lower case) as in the map data and call the column the same thing (region instead of state). In addition, it is easest if you make the column names all the same as well. Here, I am adding columns to match the three that are being plotted from the map_data and adding a region column that will allow the facetting:

stateList <-
  setNames(tolower(state.name), state.abb)

datatest$lat <- datatest$latitude
datatest$long <- datatest$longitude
datatest$group <- NA
datatest$region <- stateList[datatest$state]

Now, you can add a geom_point() line to the plot, and it will facet correctly:

ggplot(map_data('state',region=states)
       , aes(x=long,y=lat,group=group)) +
  geom_polygon(colour='black',fill='white') +
  geom_point(data = datatest) +
  facet_wrap(~region
             , scales = "free"
             , ncol=3)

Gives

Or, you can add it to the cowplot approach (note that I am just titling now and skipping the facetting).

sepStates <-
  lapply(states, function(thisState){
    ggplot(map_data('state',region=thisState)
           , aes(x=long,y=lat,group=group)) +
      geom_polygon(colour='black',fill='white') +
      geom_point(data = datatest[datatest$region == tolower(thisState), ]) +
      ggtitle(thisState) +
      coord_map() +
      theme_void() +
      theme(plot.title = element_text(hjust = 0.5))
  })

plot_grid(plotlist = sepStates)

gives



来源:https://stackoverflow.com/questions/44814768/mapping-different-states-in-r-using-facet-wrap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!