This is a pretty hacky solution that will probably need some adjustments. I switched over to sf
to make some of the spatial manipulation easier.
The first thing to do is make the map with the NA
values blank—do that by mapping NA
values to alpha, and set that alpha to 0.
I saw @JonSpring 's comment about the ggtextures
package (which looks like it's still in beta) and started messing around with it. The trick is that as of now, ggtextures
only makes bars and rectangles, not the more complex shapes needed to fill in missing areas in a map.
Instead, make a rectangle the size of the whole map and fill it with a texture (I made a little hatching SVG file here). On top of that, add a layer that will mask the water areas—otherwise the texture will be showing through there. I made the mask by taking the spatial difference between the map's bounding box and the land areas.
library(ggplot2)
library(dplyr)
library(sf)
library(ggtextures)
data(wrld_simpl, package = "maptools")
set.seed(10)
world <- st_as_sf(wrld_simpl) %>%
select(name = NAME, geometry) %>%
mutate(value = sample(c(letters[1:4], NA), size = nrow(.), replace = T))
world_bbox <- st_bbox(world)
world_inv <- st_difference(st_as_sfc(world_bbox), st_union(world)) %>%
st_combine()
First, just the mask (could be cleaner):
ggplot(world) +
geom_sf(data = world_inv, fill = "white")

Add up all the layers, and build two legends together, one for color with NA
missing, and one for image with NA
marked off.
pattern <- tibble(
xmin = world_bbox$xmin, xmax = world_bbox$xmax, ymin = world_bbox$ymin, ymax = world_bbox$ymax,
image = "diagonals"
)
ggplot(world) +
geom_textured_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, image = image),
data = pattern, img_width = unit(0.8, "in"), img_height = unit(0.8, "in")) +
geom_sf(aes(fill = value, alpha = is.na(value))) +
geom_sf(data = world_inv, fill = "white") +
scale_fill_grey(breaks = letters[1:4]) +
scale_alpha_manual(values = c("TRUE" = 0, "FALSE" = 1), guide = NULL) +
scale_image_manual(values = c("diagonals" = "hatching.svg"), name = NULL, labels = c("NA"))

Definitely still some things you'll want to tweak, but hopefully it's a start.