Show grid lines above `geom_spatraster` but below data points in `ggplot2`?

133 views Asked by At

I am drawing a raster map with points on it in ggplot2 using tidyterra:

library(ggplot2)
library(rnaturalearth)
library(terra)
library(tidyterra)

backmap <- ne_download(scale=50, type="MSR_50M", category="raster") # will download a 17MB map
data <- data.frame(longitude=runif(10, -180, 180), latitude=runif(10, -90, 90)) # simulate points

ggplot(data, aes(longitude, latitude)) +
  geom_spatraster(data=backmap) +
  geom_point() +
  coord_sf(crs='+proj=lonlat', expand=F)

Plot1

I would like to have the graticules drawn above the raster map, for now they are below it and only visible if the map is not fully opaque:

ggplot(data, aes(longitude, latitude)) +
  geom_spatraster(data=backmap, alpha=.5) +
  geom_point() +
  coord_sf(crs='+proj=lonlat', expand=F)

Plot2_alpha

I know I can have the grid above everything using theme(panel.background=element_blank(), panel.ontop=T) like described in this SO answer, but then the points are below the grid which I don't like.

I am aware of a workaround with sf::st_graticule() suggested in this SO answer but wonder if the redundancy of drawing the same grid twice can be resolved by the ggplot2 magicians.

2

There are 2 answers

2
L Tyrone On BEST ANSWER

The sf package is your friend here. Note the point in the example image just above Papua New Guinea, it's in front of the graticules. Also, it is better practice to convert all your spatial vector data, such as your points, to sf objects with defined crs. I have omitted the raster import steps but kept your object names the same:

library(tibble)
library(tidyterra)
library(sf)
library(ggplot2)

# Sample point data
set.seed(1)
data <- tibble(longitude=runif(10, -180, 180),
               latitude=runif(10, -90, 90))

# Generate graticules
graticules <- st_graticule(lon = seq(-180,180, 60),
                           lat = seq(-90,90, 30)) %>%
  vect()

ggplot() +
  geom_spatraster(data = backmap) + 
  geom_sf(data = graticules, color = "red") +
  geom_point(data = data,
          aes(x = longitude, y = latitude),
          color = "black") +
  coord_sf(expand = FALSE) +
  scale_x_continuous(breaks = seq(-180, 180, by = 60)) +
  scale_y_continuous(breaks = seq(-90, 90, by = 30)) +
  theme(legend.position = "none")

result

0
teunbrand On

I had trouble installing (tidy)terra, so I don't know if this will work for your data object, but generally, you can add a manual graticule in between your raster and points.

library(ggplot2)
library(maps)

world1 <- sf::st_as_sf(map('world', plot = FALSE, fill = TRUE))

ggplot(world1) +
  geom_sf() +
  geom_sf(data = sf::st_graticule(world1), colour = "red")
  # geom_point()

Created on 2023-12-13 with reprex v2.0.2