Search code examples
rggplot2shapefiler-sf

Overlaying two geom_sf with same data sources but differents variables types in ggplot


I want to overlay the plot 1 and 2 on the same plot. They come from the same source and I want in the backgroung the plot 1 and add plot 2 with some transparency on top.

plot1= ggplot() +
  geom_sf(data = toy,
          aes(geometry = geometry, fill = b),
          color = NA) +
  scale_fill_gradient(low="white", high="#0099FF")

plot2= ggplot() +
  geom_sf(data = toy ,
          aes(geometry = geometry, fill = a),
          color = NA) +
  scale_fill_manual(values=c(alpha("#CCCCCC",0), alpha("#990033",1)))

The work well independently, but I do no manage to combine them. I tried the following things but got some errors

ggplot() +
  geom_sf(data = toy,
          aes(geometry = geometry, fill = b),
          color = NA) +
  scale_fill_gradient(low="white", high="#0099FF") +
  geom_sf(data = toy ,
          aes(geometry = geometry, fill = a),
          color = NA) +
  scale_fill_manual(values=c(alpha("#CCCCCC",0), alpha("#990033",1)))
#> Scale for 'fill' is already present. Adding another scale for 'fill', which
#> will replace the existing scale.
#> Error: Continuous value supplied to discrete scale

To execute the code use :

library(sf)
library(ggplot2)

The structure of my toy data is as follow :

structure(list(a = structure(c(1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 
1L, 2L), .Label = c("0", "1"), class = "factor"), b = c(0.22798252850771, 
0.743008424993604, 0.388169342186302, 0.907995192101225, 0.953832301311195, 
0.40455531864427, 0.363415864063427, 0.805322113214061, 0.519045175751671, 
0.484226288506761), geometry = structure(list(structure(list(
    structure(c(1223540.00733145, 1223540.00733145, 1224040.00733145, 
    1224040.00733145, 1223540.00733145, 6046527.88033381, 6047027.88033381, 
    6047027.88033381, 6046527.88033381, 6046527.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1224040.00733145, 1224040.00733145, 1224540.00733145, 
    1224540.00733145, 1224040.00733145, 6046527.88033381, 6047027.88033381, 
    6047027.88033381, 6046527.88033381, 6046527.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1224540.00733145, 1224540.00733145, 1225040.00733145, 
    1225040.00733145, 1224540.00733145, 6046527.88033381, 6047027.88033381, 
    6047027.88033381, 6046527.88033381, 6046527.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1225040.00733145, 1225040.00733145, 1225540.00733145, 
    1225540.00733145, 1225040.00733145, 6046527.88033381, 6047027.88033381, 
    6047027.88033381, 6046527.88033381, 6046527.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1223540.00733145, 1223540.00733145, 1224040.00733145, 
    1224040.00733145, 1223540.00733145, 6047027.88033381, 6047527.88033381, 
    6047527.88033381, 6047027.88033381, 6047027.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1224040.00733145, 1224040.00733145, 1224540.00733145, 
    1224540.00733145, 1224040.00733145, 6047027.88033381, 6047527.88033381, 
    6047527.88033381, 6047027.88033381, 6047027.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1224540.00733145, 1224540.00733145, 1225040.00733145, 
    1225040.00733145, 1224540.00733145, 6047027.88033381, 6047527.88033381, 
    6047527.88033381, 6047027.88033381, 6047027.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1225040.00733145, 1225040.00733145, 1225540.00733145, 
    1225540.00733145, 1225040.00733145, 6047027.88033381, 6047527.88033381, 
    6047527.88033381, 6047027.88033381, 6047027.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1224040.00733145, 1224040.00733145, 1224540.00733145, 
    1224540.00733145, 1224040.00733145, 6047527.88033381, 6048027.88033381, 
    6048027.88033381, 6047527.88033381, 6047527.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg")), structure(list(
    structure(c(1224540.00733145, 1224540.00733145, 1225040.00733145, 
    1225040.00733145, 1224540.00733145, 6047527.88033381, 6048027.88033381, 
    6048027.88033381, 6047527.88033381, 6047527.88033381), .Dim = c(5L, 
    2L))), class = c("XY", "POLYGON", "sfg"))), class = c("sfc_POLYGON", 
"sfc"), precision = 0, bbox = structure(c(xmin = 1223540.00733145, 
ymin = 6046527.88033381, xmax = 1225540.00733145, ymax = 6048027.88033381
), class = "bbox"), crs = structure(list(input = NA_character_, 
    wkt = "PROJCS[\"RGF_1993_Lambert_93\",\n    GEOGCS[\"GCS_RGF_1993\",\n        DATUM[\"Reseau_Geodesique_Francais_1993\",\n            SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],\n        PRIMEM[\"Greenwich\",0.0],\n        UNIT[\"Degree\",0.017453292519943295]],\n    PROJECTION[\"Lambert_Conformal_Conic_2SP\"],\n    PARAMETER[\"False_Easting\",700000.0],\n    PARAMETER[\"False_Northing\",6600000.0],\n    PARAMETER[\"Central_Meridian\",3.0],\n    PARAMETER[\"Standard_Parallel_1\",49.0],\n    PARAMETER[\"Standard_Parallel_2\",44.0],\n    PARAMETER[\"Latitude_Of_Origin\",46.5],\n    UNIT[\"Meter\",1.0]]"), class = "crs"), n_empty = 0L)), row.names = c(NA, 
10L), sf_column = "geometry", agr = structure(c(a = NA_integer_, 
b = NA_integer_), .Label = c("constant", "aggregate", "identity"
), class = "factor"), class = c("sf", "tbl_df", "tbl", "data.frame"
))

Solution

  • The problem is probably due to the fact that we want to define two different fill scales for two different variables: a which is categorical, and b continuous. To do this, we can use the small (but very useful) ggnewscale library: https://eliocamp.github.io/ggnewscale/ which allows us to redefine a new scale in the same plot:

    install.packages("ggnewscale")
    library(ggnewscale)
    
    ggplot(data = toy) + 
       geom_sf(aes(geometry = geometry, fill = a)) + 
       scale_fill_manual(values = c("#FFFFFF00", "red")) +
       new_scale_fill() + 
       geom_sf(aes(geometry = geometry, fill = b, alpha = 0.5))
    

    Notice the new_scale_fill() call before plotting the next layer, this allows us to use a different scale for this second layer.