Mapping different states in R using facet wrap

前端 未结 1 747
执笔经年
执笔经年 2021-01-07 02:17

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 contain

相关标签:
1条回答
  • 2021-01-07 02:31

    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

    0 讨论(0)
提交回复
热议问题