Object 'value' not found when trying to add border color to choroplethr county map

127 views Asked by At

I want to add black borders to a county choropleth map I have created of New Jersey. Here is my current code:

    county_choropleth(tni_data,
                  state_zoom = "new jersey",
                  reference_map = TRUE,
                  num_colors = 8) +
  scale_fill_brewer(palette="YlOrRd") +
  labs(title = "DV/SV Incidents by New Jersey County",
       legend = "DV/SV Incidents (total)") + 
  geom_polygon(aes(fill=value), color="black")

Based on this earlier question.

I am getting this error:

Error in FUN(X[[i]], ...) : object 'value' not found

Any advice on what might be wrong would be very appreciated!

UPDATE: Including minimal reproducible example!

tni_data <- structure(list(county = c("atlantic", "bergen", "burlington", 
"camden", "cape may", "cumberland", "essex", "gloucester", "hudson", 
"hunterdon", "mercer", "middlesex", "monmouth", "morris", "ocean", 
"passaic", "salem", "somerset", "sussex", "union", "warren"), 
    value = c(3187, 3410, 3747, 6532, 1339, 2510, 6420, 2417, 
    2656, 570, 2139, 4336, 3514, 1802, 4372, 2451, 773, 1840, 
    1265, 3054, 1311), region = c(34001, 34003, 34005, 34007, 
    34009, 34011, 34013, 34015, 34017, 34019, 34021, 34023, 34025, 
    34027, 34029, 34031, 34033, 34035, 34037, 34039, 34041), 
    county.fips.character = c("34001", "34003", "34005", "34007", 
    "34009", "34011", "34013", "34015", "34017", "34019", "34021", 
    "34023", "34025", "34027", "34029", "34031", "34033", "34035", 
    "34037", "34039", "34041"), state.name = c("new jersey", 
    "new jersey", "new jersey", "new jersey", "new jersey", "new jersey", 
    "new jersey", "new jersey", "new jersey", "new jersey", "new jersey", 
    "new jersey", "new jersey", "new jersey", "new jersey", "new jersey", 
    "new jersey", "new jersey", "new jersey", "new jersey", "new jersey"
    ), state.fips.character = c("34", "34", "34", "34", "34", 
    "34", "34", "34", "34", "34", "34", "34", "34", "34", "34", 
    "34", "34", "34", "34", "34", "34"), state.abb = c("NJ", 
    "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", 
    "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ", "NJ"
    ), tni.per.capita = c(0.0120870785451511, 0.00365800545375359, 
    0.00841362616734292, 0.0128970859140997, 0.0145481806625452, 
    0.0167862660255339, 0.00803529522200319, 0.00828772853831489, 
    0.00395008261562097, 0.00458306196782208, 0.00582151702365076, 
    0.00525536262729346, 0.00567877891708886, 0.00366375585804471, 
    0.00720042952241982, 0.00488416303659037, 0.0123907990702893, 
    0.00559382733314282, 0.00900432777176698, 0.00548943903109783, 
    0.0124540454273419)), class = "data.frame", row.names = c(NA, 
-21L))

county_choropleth(tni_data,
                  state_zoom = "new jersey",
                  reference_map = TRUE,
                  num_colors = 8) +
  scale_fill_brewer(palette="YlOrRd") +
  labs(title = "DV/SV Incidents by New Jersey County",
       legend = "DV/SV Incidents (total)") + 
  geom_polygon(aes(fill=value), color="black")
2

There are 2 answers

5
Ari On BEST ANSWER

Here is a minimium reproducible example that I believe shows your situation:

library(choroplethr)
library(choroplethrMaps)

# draw map to show "problem" - no borders on counties
county_choropleth(df_pop_county, state_zoom = "new jersey")

enter image description here

From your comment below, it sounds like you want to add a colored border to this map.

The key point is this: All choroplethr functions return ggplot2 objects. So while there is no parameter to county_choropleth like set_border_color, that's actually not a problem. We can add that border ourselves by writing code like the following:

county_choropleth(...) + geom_polygon(...)

The complication is that is that the new layer (geom_polygon) needs its own data. And that data needs to be a map of NJ counties. Getting that map is a 2-step process:

1. Get a vector of NJ FIPS codes (AKA "regions")

You might not know this, but choroplethrMaps ships with a dataframe called county.regions that contains the FIPS code of every county in the US. We're going to use it to get the FIPS codes of every county in New Jersey.

library(tidyverse)

data(county.regions)
nj_regions = filter(county.regions, state.name == "new jersey") %>% pull(region)

nj_regions

Note that choroplethr calls these regions because it's a neutral term that can be used with multiple geographies. I.e., whether dealing with states, counties, countries or zip codes, we can always use the term "region".

2. Subselect the county map to just NJ

You might not know this, but choroplethrMaps ships with the actual county map it uses to render the counties. It is called county.map. Now that we have the regions (i.e. FIPS codes) that we want to subselect, we can do so like this:

data(county.map)

nj.county.map = filter(county.map, region %in% nj_regions)

3. Add the border as a new layer

And now we can add the NJ county map as a border with its own color. Note that we use fill = NA here to ensure that this layer is rendered as a border (and not filled in). Here I use yellow, but obviously you can change it as you see fit:

county_choropleth(df_pop_county, state_zoom = "new jersey") +
  geom_polygon(data = nj.county.map, 
               aes(long, lat, group = group), 
               color = "yellow", 
               fill = NA, 
               size = 0.2)

enter image description here

As an FYI, I have created three, full-length courses on choroplethr (see here). All are now free. They might help you as well.

I always wanted to create a fourth that dealt with issues like this: mixing choroplethr and ggplot2 to create custom maps. Questions like yours have come up quite a bit. One reason I'm giving such a detailed answer here is that I don't think I'll ever get around to creating a course like that. But hopefully this answer can help both you and the next person who has this question. The structure to these solutions tends to be the same: use the helper data structures (e.g. county.map and county.regions) in some custom way, and then add a new ggplot2 layer.

2
SarahS On

Did you define the term "value"? For colors/fills, you would need to have a categorization column of what you're basing color groups on.

So, for the example they linked, they defined fakedata$value as runif(n=56, min=0, max=1). But that's to color in polygons.

If you just want a black border, I think geom_polygon(aes(color = "black")) should do it? It's difficult to tell without understanding what the data of tni_data looks like.