How to show the zip codes when using zip_choropleth?

251 Views Asked by At

I've created a choropleth map of zip codes within a given county. However, I'm being asked to label all the zip codes (it might be cluttered but this is what they want to see). Is there a way to add all the labels directly on the map? Similar to labeling all the states in a U.S Choropleth map?

I essentially want all the 'regions' labeled.

Here is my code:

EDIT: Here's the code that works. Big thanks to Stanleh for the help!

library(tidyverse)
library(maps)
library(ggplot2)
library(ggmap)
library(mapproj)
library(choroplethr)
library(choroplethrZip)

df <- structure(list(region = c("45001", "45002", "45003", "45011", 
"45013", "45014", "45030", "45041", "45044", "45050", "45052", 
"45069", "45111", "45140", "45147", "45150", "45174", "45202", 
"45203", "45204", "45205", "45206", "45207", "45208", "45209", 
"45210", "45211", "45212", "45213", "45214", "45215", "45216", 
"45217", "45218", "45219", "45220", "45223", "45224", "45225", 
"45226", "45227", "45229", "45230", "45231", "45232", "45233", 
"45236", "45237", "45238", "45239", "45240", "45241", "45242", 
"45243", "45244", "45246", "45247", "45248", "45249", "45250", 
"45251", "45252", "45255", "45033", "45051"), value = c(3, 20, 
1, 11, 155, 7, 28, 1, 2, 1, 3, 5, 1, 20, 1, 73, 1, 52, 26, 15, 
106, 109, 52, 8, 55, 1, 185, 69, 30, 99, 104, 35, 35, 9, 20, 
96, 51, 182, 75, 3, 82, 133, 60, 246, 42, 13, 79, 217, 128, 146, 
125, 71, 30, 10, 19, 62, 24, 21, 31, 1, 51, 3, 28, 0, 0)), row.names = c(NA, 
-65L), class = c("tbl_df", "tbl", "data.frame"))

fip=c(39061)

ohiocounty_map <-
  map_data("county") %>%
  subset(region == "ohio") %>%
  mutate(County = str_to_sentence(subregion)) %>%
  group_by(County) %>%
  filter(County %in% c("Hamilton"))

# get zip codes
data("zip.map")

myzips <- zip.map %>%
  filter(region %in% df$region) %>% 
  rename(zipcode = region) %>% 
  group_by(zipcode) %>% 
  summarise(across(everything(), ~mean(.x, na.rm = TRUE)))


choropleth <-  zip_choropleth(df, state_zoom = "ohio", county_zoom = fip, 
                              title = "Population by Zip Code in Hamilton County", 
                              legend= "Number of Clients")

choropleth + geom_polygon(data=ohiocounty_map, aes(x=long, y=lat, group=group), alpha=0, 
                          color="black", 
                          size=0.2) +
  guides(fill=guide_legend(title="Number of Clients")) +
  theme(plot.margin = margin(r=.8, l=.5, t=.6, b=.8, unit="in"), plot.title = element_text(hjust=0.5, face="bold", size = 15)) +
  coord_cartesian(xlim=c(-84.9, -84.25), ylim=c(39, 39.33), expand = FALSE) + 
  geom_text(data = myzips, 
            stat = "identity", 
            check_overlap = TRUE,
            aes(x = long, y = lat, label = zipcode))  
1

There are 1 best solutions below

2
jrcalabrese On

One way to accomplish this is to bring in zip.map and filter by the zipcodes you want. Now you have longitudinal and latitude data for your zipcodes and can add it to your existing map with geom_text or geom_label.

library(tidyverse)
library(maps)
library(ggplot2)
library(ggmap)
library(mapproj)
library(choroplethr)
library(choroplethrZip)

df <- structure(list(region = c("45001", "45002", "45003", "45011", 
                                "45013", "45014", "45030", "45041", "45044", "45050", "45052", 
                                "45069", "45111", "45140", "45147", "45150", "45174", "45202", 
                                "45203", "45204", "45205", "45206", "45207", "45208", "45209", 
                                "45210", "45211", "45212", "45213", "45214", "45215", "45216", 
                                "45217", "45218", "45219", "45220", "45223", "45224", "45225", 
                                "45226", "45227", "45229", "45230", "45231", "45232", "45233", 
                                "45236", "45237", "45238", "45239", "45240", "45241", "45242", 
                                "45243", "45244", "45246", "45247", "45248", "45249", "45250", 
                                "45251", "45252", "45255", "45033", "45051"), value = c(3, 20, 
                                                                                        1, 11, 155, 7, 28, 1, 2, 1, 3, 5, 1, 20, 1, 73, 1, 52, 26, 15, 
                                                                                        106, 109, 52, 8, 55, 1, 185, 69, 30, 99, 104, 35, 35, 9, 20, 
                                                                                        96, 51, 182, 75, 3, 82, 133, 60, 246, 42, 13, 79, 217, 128, 146, 
                                                                                        125, 71, 30, 10, 19, 62, 24, 21, 31, 1, 51, 3, 28, 0, 0)), row.names = c(NA, 
                                                                                                                                                                 -65L), class = c("tbl_df", "tbl", "data.frame"))

fip=c(39061)

ohiocounty_map <-
  map_data("county") %>%
  subset(region == "ohio") %>%
  mutate(County = str_to_sentence(subregion)) %>%
  group_by(County) %>%
  filter(County %in% c("Hamilton"))

# get zip codes
data("zip.map")
myzips <- zip.map %>%
  filter(region %in% df$region) %>%
  rename(zipcode = region) %>%
  group_by(zipcode) %>% 
  summarise(across(everything(), mean)) # without this line, there would be a lot of zip code labels

choropleth <-  zip_choropleth(df, state_zoom = "ohio", county_zoom = fip, 
                              title = "Population by Zip Code in Hamilton County", 
                              legend= "Number of Clients")

choropleth + geom_polygon(data=ohiocounty_map, aes(x=long, y=lat, group=group), alpha=0, 
                          color="black", 
                          size=0.2) +
  scale_fill_brewer(palette="OrRd") + 
  guides(fill=guide_legend(title="Number of Clients")) +
  theme(plot.margin = margin(r=.8, l=.5, t=.6, b=.8, unit="in"), plot.title = element_text(hjust=0.5, face="bold", size = 15)) +
  coord_cartesian(xlim=c(-84.9, -84.25), ylim=c(39, 39.33), expand = FALSE) + 
  geom_text(data = myzips, 
            stat = "identity", 
            check_overlap = TRUE,
            aes(x = long, y = lat, label = zipcode))