Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arrange ggplot facets in the shape of the US

Tags:

r

ggplot2

I have a ggplot with one facet for each US state. I would like to arrange these facets in the shape of the US with a ragged border (ordered like the second map, but without Hawaii or Alaska).

To do this, I created a state-level factor variable that is ordered by US state, as read from left to right on a map. This factor also contains "space holders" for blank facets that I'd like to remove. I followed the advice of this post (see the Edit to the provided answer) but names(g$grobs) is NULL, so I can't implement their answer. Any ideas what I can do?

Here is my code:

library(ggplot2)
library(fivethirtyeight)
library(dplyr)
library(gridExtra)

data("police_deaths")
police_deaths_count <- police_deaths %>% arrange(state, -year) %>% group_by(state, year) %>% count()
police_deaths_count <- police_deaths_count %>% arrange(state, -year) %>% 
  filter(year %in% c(1970:2015) & !state %in% c("AK", "HI", "US", "GU", "MP", "PR", "RR", "TR", "VI"))

police_deaths_count$state.name <- state.name[match(police_deaths_count$state, state.abb)]
police_deaths_count$state.name[police_deaths_count$state == "DC"] <- "Washington DC"

police_deaths_count$state.reorder <- factor(police_deaths_count$state.name,
                                         levels = c("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "Maine",
                                                    "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19", "Vermont", "New Hampshire",
                                                    "Washington", "Idaho", "Montana", "North Dakota", "Minnesota", "Illinois", "Wisconsin", "Michigan", "New York", "Massachusetts", "Rhode Island",
                                                    "Oregon", "Nevada", "Wyoming", "South Dakota", "Iowa", "Indiana", "Ohio", "Pennsylvania", "New Jersey", "Connecticut", "e20",
                                                    "California", "Utah", "Colorado", "Nebraska", "Missouri", "Kentucky", "West Virginia", "Virginia", "Maryland", "Washington DC", "e21",
                                                    "e22", "Arizona", "New Mexico", "Kansas", "Arkansas", "Tennessee", "North Carolina", "South Carolina", "Delaware", "e23", "e24",
                                                    "e25", "e26", "e27", "Oklahoma", "Louisiana", "Mississippi", "Alabama", "Georgia", "e28", "e29",
                                                    "e30", "e31", "e32", "e33", "Texas", "e34", "e35", "e36", "e37", "Florida"))

police_deaths_count2 <- police_deaths_count %>% filter(!(state=="NY" & year==2001))

plot1 <- ggplot(subset(police_deaths_count2, is.na(state.name)==F), #take away 9-11 peak to see trends without it
               aes(y = n, x = year)) +
  geom_line() + 
  facet_wrap( ~ state.reorder, ncol = 11, drop = F) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ylab("Count of police deaths") +
  xlab("Year")

#the order of these facets is what I want. From here, I'd like to display the facets e1, e2, ..., e37 as completely blank by removing their facet strips and panels.
plot1

#A SO post (next line) provides a potential solution, but it doesn't work for me
#https://stackoverflow.com/questions/30372368/adding-empty-graphs-to-facet-wrap-in-ggplot2 
g <- ggplotGrob(plot1)
names(g$grobs) #this is NULL so I can't implement the SO answer.
g$layout$name
like image 705
corinne r Avatar asked Feb 23 '17 17:02

corinne r


People also ask

How do you reorder facets?

To reorder the facets accordingly of the given ggplot2 plot, the user needs to reorder the levels of our grouping variable accordingly with the help of the levels function and required parameter passed into it, further it will lead to the reordering of the facets accordingly in the R programming language.

What are facets in Ggplot?

The facet approach partitions a plot into a matrix of panels. Each panel shows a different subset of the data. This R tutorial describes how to split a graph using ggplot2 package. There are two main functions for faceting : facet_grid()

What is facet wrap in ggplot2?

facet_wrap() makes a long ribbon of panels (generated by any number of variables) and wraps it into 2d. This is useful if you have a single variable with many levels and want to arrange the plots in a more space efficient manner. You can control how the ribbon is wrapped into a grid with ncol , nrow , as.

What is the function of Facet_grid () in Ggplot ()?

facet_grid() forms a matrix of panels defined by row and column faceting variables. It is most useful when you have two discrete variables, and all combinations of the variables exist in the data.


3 Answers

A hack-ish option would be to create unique blank strip labels for the empty facets, so that they can be used as placeholders, but without creating any visible strip labels. It would probably also be better to use state abbreviations instead of full names, but I haven't done that here. Here's an example:

library(ggplot2)
library(fivethirtyeight)
library(dplyr)
library(gridExtra)

data("police_deaths")
police_deaths_count <- police_deaths %>% arrange(state, -year) %>% group_by(state, year) %>% count()
police_deaths_count <- police_deaths_count %>% arrange(state, -year) %>% 
  filter(year %in% c(1970:2015) & !state %in% c("AK", "HI", "US", "GU", "MP", "PR", "RR", "TR", "VI"))

# Create unique blank strip labels for empty facets
bl = sapply(1:37, function(n) paste(rep(" ",n),collapse=""))

police_deaths_count$state.name <- state.name[match(police_deaths_count$state, state.abb)]
police_deaths_count$state.name[police_deaths_count$state == "DC"] <- "Washington DC"

police_deaths_count$state.reorder <- factor(police_deaths_count$state.name,
                                            levels = c(bl[1:10], "Maine",
                                                       bl[11:19], "Vermont", "New Hampshire",
                                                       "Washington", "Idaho", "Montana", "North Dakota", "Minnesota", "Illinois", "Wisconsin", "Michigan", "New York", "Massachusetts", "Rhode Island",
                                                       "Oregon", "Nevada", "Wyoming", "South Dakota", "Iowa", "Indiana", "Ohio", "Pennsylvania", "New Jersey", "Connecticut", bl[20],
                                                       "California", "Utah", "Colorado", "Nebraska", "Missouri", "Kentucky", "West Virginia", "Virginia", "Maryland", "Washington DC", bl[21],
                                                       bl[22], "Arizona", "New Mexico", "Kansas", "Arkansas", "Tennessee", "North Carolina", "South Carolina", "Delaware", bl[23:24],
                                                       bl[25:27], "Oklahoma", "Louisiana", "Mississippi", "Alabama", "Georgia", bl[28:29],
                                                       bl[30:33], "Texas", bl[34:37], "Florida"))


police_deaths_count2 <- police_deaths_count %>% filter(!(state=="NY" & year==2001))

plot1 <- ggplot(subset(police_deaths_count2, is.na(state.name)==F), #take away 9-11 peak to see trends without it
                aes(y = n, x = year)) +
  geom_line() + 
  facet_wrap( ~ state.reorder, ncol = 11, drop = F, strip.position="bottom") +
  theme_classic() +
  theme(axis.text.x = element_blank(),
        strip.background=element_blank(),
        axis.line=element_blank(),
        axis.ticks=element_blank()) +
  ylab("Count of police deaths") +
  xlab("Year (1970 - 2015)")

enter image description here

like image 65
eipi10 Avatar answered Oct 12 '22 20:10

eipi10


The geofacet package should work nicely: https://github.com/hafen/geofacet

like image 24
Phil Avatar answered Oct 12 '22 19:10

Phil


There is a function called glyphs in the GGally package which can make these.

like image 24
Dianne Cook Avatar answered Oct 12 '22 19:10

Dianne Cook