I am trying to create a map where only counties with missing data have a striped pattern. Ideally, the background of this pattern would be white and the stripes would be blue, but I have gotten totally stumped on how to achieve this. I have to combined geom_polygon and geom_polygon_pattern, and in both cases I map the fill aesthetic to the same value. The issue becomes how to specify the fill color for the geom_polygon_pattern, which is mapped using a dataframe of counties with only NA values for the fill color variable.
Here's a sample of some of the data below generated with the dput function intended to help with reproduction, but I think the principle should be the same for manipulating the fill of any geom_*_pattern geom:
library(maps)
library(ggplot2)
library(ggpattern)
library(dplyr)
data(county.fips)
states <- map_data("state")
counties <- structure(list(long = c(-111.050682067871, -111.491851806641,
-111.5205078125, -111.5205078125, -111.537689208984, -111.577796936035,
-111.606452941895, -111.606452941895, -111.600723266602, -111.640830993652,
-111.629364013672, -111.594993591309, -111.600723266602, -111.572067260742,
-111.577796936035, -111.612174987793, -111.600723266602, -111.594993591309,
-111.600723266602, -111.617904663086), lat = c(41.9978065490723,
41.9978065490723, 42.0035362243652, 42.043643951416, 42.0665626525879,
42.0894813537598, 42.0952110290527, 42.1181259155273, 42.1467742919922,
42.1926116943359, 42.2556381225586, 42.2728271484375, 42.3186645507812,
42.3473091125488, 42.3759574890137, 42.4103355407715, 42.4275245666504,
42.4389839172363, 42.4619026184082, 42.4733619689941), group = c(520,
520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520,
520, 520, 520, 520, 520, 520), indAnyDisaster_frequency_v2 = structure(c(NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_), levels = c("0",
"1-2", "3-5", "6-8", "9-12", "13-19"), class = "factor")), row.names = 19621:19640, class = "data.frame")
indAnyDisaster_map_wNA_6groups <-
ggplot() +
coord_fixed(1.3) +
geom_polygon_pattern(data = filter(counties, is.na(indAnyDisaster_frequency_v2)),
mapping = aes(x = long,
y = lat,
group = group,
fill = indAnyDisaster_frequency_v2),
color = "grey", linewidth = 0.05,
# fill = 'white',
pattern = 'stripe',
pattern_density = .01,
pattern_spacing = .01,
pattern_colour = 'white',
pattern_size = .25,
na.rm = TRUE) +
geom_polygon(data = filter(counties, !is.na(indAnyDisaster_frequency_v2)),
mapping = aes(x = long,
y = lat,
group = group,
fill = indAnyDisaster_frequency_v2),
color = "grey", size = 0.05,
na.rm = TRUE) +
geom_polygon(data = states,
mapping = aes(x = long, y = lat, group = group),
color = "black", size = 0.1, fill = NA) +
theme_bw() +
theme(axis.text = element_blank(),
axis.line = element_blank(),
axis.ticks = element_blank(),
panel.border = element_blank(),
panel.grid = element_blank(),
axis.title = element_blank()) +
labs(title = "All Disaster Types",
fill = "Count") +
scale_fill_manual(breaks = c("0", "1-2", "3-5", "6-8", "9-12", "13-19", NA),
values = c("white","#deebf7","#9ecae1","#4292c6","#08519c", "#08306b", "white")) +
scale_pattern_fill_manual(na.value = c("white"))
I have resorted to using white stripes to stand out against the grey fill, but as you can (possibly) tell from my code, I would really prefer that the background is white so I can specify a shade of blue for the bars. I am a little confused about how to do this given that the fill parameter is in the aesthetic mapping of two different geoms, but clearly I can control the legend order in a single scale_fill_manual call. I also tried setting the na.value argument of scale_fill_manual to white, but I get the following error:
Error in UseMethod("depth") :
no applicable method for 'depth' applied to an object of class "NULL"
I tried setting fill directly in geom_polygon_pattern, but then this overrides the fill mapping to indAnyDisaster_frequency_v2 and it no longer appears in the legend. Any ideas on what I should be doing instead would be appreciated!
Instead of mapping indAnyDisaster_frequency_v2
on the fill
aesthetic you could map an arbitrary character value on the fill
aes, e.g. in the code below I use "NA_value"
. Then you can easily assign your desired blue color to this category:
library(ggplot2)
library(ggpattern)
ggplot() +
coord_fixed(1.3) +
geom_polygon_pattern(
data = dplyr::filter(counties, is.na(indAnyDisaster_frequency_v2)),
mapping = aes(
x = long,
y = lat,
group = group,
fill = "NA_value"
),
color = "grey", linewidth = 0.05,
pattern = "stripe",
pattern_density = .01,
pattern_spacing = .01,
pattern_colour = "white",
pattern_size = .25,
na.rm = TRUE
) +
geom_polygon(
data = dplyr::filter(counties, !is.na(indAnyDisaster_frequency_v2)),
mapping = aes(
x = long,
y = lat,
group = group,
fill = indAnyDisaster_frequency_v2
),
color = "grey", size = 0.05,
na.rm = TRUE
) +
# geom_polygon(
# data = states,
# mapping = aes(x = long, y = lat, group = group),
# color = "black", size = 0.1, fill = NA
# ) +
theme_bw() +
theme(
axis.text = element_blank(),
axis.line = element_blank(),
axis.ticks = element_blank(),
panel.border = element_blank(),
panel.grid = element_blank(),
axis.title = element_blank()
) +
labs(
title = "All Disaster Types",
fill = "Count"
) +
scale_fill_manual(
breaks = c("0", "1-2", "3-5", "6-8", "9-12", "13-19", "NA_value"),
values = c("white", "#deebf7", "#9ecae1", "#4292c6", "#08519c", "#08306b", "blue")
)
#> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` instead.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.