rggplot2

Allowing for panel.grid to be in foreground or in background in ggplot2


I am plotting a map of Europe with ggplot2 and I would like to show meridians and parallels. I can do this using panel.grid.major and panel.grid.minor.

However, with my current code, the grid created with ggplot is in background compared to the plotted surface (the countries), so that when the two overlap the grid cannot be seen:

library(rnaturalearth)
library(ggplot2)
library(sf)


ggplot(ne_countries(scale = "medium", continent = NULL, returnclass = "sf")) +
  geom_sf() +
  coord_sf(xlim=c(2600000, 7300000), ylim=c(5450000, 1000000), 
           crs = st_crs(3035)) +
  theme(panel.background = element_rect(fill = "white"),
        panel.grid.major = element_line(colour = "red"),
        panel.grid.minor = element_line(colour = "red"))

enter image description here

This is not optimal, as I would like to always see meridians and parallels, even when overlapping with the countries' geometries.

Is there a way to let the grid be in foreground and the plotted surface in background in ggplot2?


Solution

  • You can use theme(panel.ontop = TRUE), but you need to make your panel background transparent for this to work. This is not a problem if your panel background is the same colour as your plot background, as is the case here.

    ggplot(ne_countries(scale = "medium", continent = NULL, returnclass = "sf")) +
      geom_sf() +
      coord_sf(xlim=c(2600000, 7300000), ylim=c(5450000, 1000000), 
               crs = st_crs(3035)) +
      theme(panel.background = element_blank(),
            panel.grid.major = element_line(colour = "red"),
            panel.grid.minor = element_line(colour = "red"),
            panel.ontop = TRUE)
    

    enter image description here

    For the more general case (say you wanted the oceans to be blue, or you wanted white oceans but a gray plot background), your options are to draw a large polygon representing the ocean underneath your map to act as the panel background, or to draw a grid over the map as an sf object. The former is easier.

    ocean <- st_point(c(0, 0)) |>
      st_sfc(crs = "WGS84") |>
      st_buffer(1e7) |>
      st_as_sf()
    
    ggplot(ne_countries(scale = "medium", continent = NULL, returnclass = "sf")) +
      geom_sf(data = ocean, fill = "lightblue") +
      geom_sf() +
      coord_sf(xlim=c(2600000, 7300000), ylim=c(5450000, 1000000), 
               crs = st_crs(3035)) +
      theme(panel.background = element_blank(),
            panel.grid.major = element_line(colour = "red"),
            panel.grid.minor = element_line(colour = "red"),
            panel.ontop = TRUE)
    

    enter image description here