Search code examples
rggplot2joincolorsna

Color column and exclude NA with ggplot2


I would like to color a column but render the NA values one specific color with ggplot2 please. If we take the world dataset from the spData package.

library(sf)
library(spData)
library(ggplot2)

set.seed(2018) # set seed for reproducibility
(bb = st_bbox(world)) # the world's bounds
random_df = data.frame(
  x = runif(n = 10, min = bb[1], max = bb[3]),
  y = runif(n = 10, min = bb[2], max = bb[4])
)
random_points = random_df |> 
  st_as_sf(coords = c("x", "y"), crs = "EPSG:4326") # set coordinates and CRS

p1 <- ggplot(world) + 
  geom_sf(color = "gray", fill = "white") +
  geom_sf(data = random_points, color = "black", shape = 4, lwd = 3) +
  coord_sf(datum = NA) 

p1

enter image description here

I want only points that are on land

world_random = world[random_points, ]
nrow(world_random)
random_joined = st_join(random_points, world["name_long"])

My attempt:

random_joined$name_long = as.character(random_joined$name_long)

p1 <- ggplot(world) +  
  geom_sf(color = "gray", fill = "white") +
  geom_sf(data = random_joined, aes(fill = name_long), shape = 16) + #,  color = "white") +
  scale_fill_manual(values = c("blue", "yellow", "red", "orange", "white")) +
  coord_sf(datum = NA)

p1

enter image description here

How do I show the named countries in different colours and the NA on one color?
I would prefer to not use scale_fill_manual but another method that programmatrically understand the value is NA or a country name please.


Solution

  • As you have set shape=16 for your points you have to map on the color aes as shape=16 does not support the fill aes and use scale_color_manual. And if you want a specific color for the NAs you could do so via the na.value= argument of scale_color_manual.

    library(ggplot2)
    
    p1 <- ggplot(world) +
      geom_sf(color = "gray", fill = "white") +
      # Map on the color aes
      geom_sf(data = random_joined, aes(color = name_long), shape = 16) + # ,  color = "white") +
      scale_color_manual(
        values = c("blue", "yellow", "red", "orange", "white")
      ) +
      coord_sf(datum = NA)
    
    p1
    

    enter image description here