Search code examples
rggplot2colors

Plot the legend at the bottom in different way when we deal with discrete color filling in ggplot


Suppose we want to plot this data:

library(ggplot2)
library(sf)
library(raster)
library(colorRamps)

min_lon <- 10
max_lon <- 17
min_lat <- 8
max_lat <- 17
grid_size <- 0.5
lon_grids <- 1 + ((max_lon - min_lon)/grid_size)
lat_grids <- 1 + ((max_lat - min_lat)/grid_size)
points <- data.frame(lon = rep(seq(min_lon, max_lon, grid_size), lat_grids), lat = rep(seq(min_lat, max_lat, grid_size), each = lon_grids))

points$Var <- runif(min= 10, max = 48,  285)
points$value <-cut(points$Var, breaks= seq(10.08, 47.80, length.out = 13), dig.lab = 1)
ggplot() +
  coord_sf(xlim = c(min_lon, max_lon), ylim = c(min_lat, max_lat)) +
  theme_bw()+
  geom_raster(data = points, aes(x = lon, y = lat, fill = value), interpolate = FALSE) +
  labs(x="Longitude", y="Latitude")+
  scale_fill_manual(values = matlab.like(n = 13), name = "[m]", 
                    labels = sprintf("%.2f", seq(10.08, 47.80, length.out = 13)),
                    guide = guide_legend(reverse = TRUE))+theme(legend.position = "bottom")

This code produces the following graph: enter image description here

Two problems I am facing here:

  1. To make it discrete, I used the cut function. I chose the breaks= seq(10.08, 47.80, length.out = 13) arbitrary based on the minimum and maximum values with a random length of 13. Is there any criteria to decide the correct range?

  2. Is there any way to make the legend look like this?

enter image description here


Solution

  • One option would be to use e.g. scale_fill_stepsn with guide_binswhich does not require to manually discretize the variable mapped on fill. Additionally I use a custom function to set the breaks of the legend instead of the default mechanism to set the number of breaks.

    set.seed(123)
    
    library(ggplot2)
    library(colorRamps)
    
    base <- ggplot() +
      coord_sf(xlim = c(min_lon, max_lon), ylim = c(min_lat, max_lat)) +
      theme_bw() +
      geom_raster(data = points, aes(x = lon, y = lat), interpolate = FALSE) +
      labs(x = "Longitude", y = "Latitude") +
      theme(legend.position = "bottom")
    
    base +
      aes(fill = Var) +
      scale_fill_stepsn(colors = matlab.like(n = 13), name = "[m]",
                        breaks = function(x) seq(x[[1]], x[[2]], length.out = 13),
                        labels = ~ sprintf("%.0f", .x),
                        guide = guide_bins(axis = FALSE,
                                           show.limits = TRUE))
    

    enter image description here