ggplot2ggmaptile

Add a geom_scatterpie to a geom_tile - Problem while converting geom to grob


I do not fufil to use geom_scatterpie on a ggplot layer made using get_tiles and geom_tile. I always get the following error:

Error: ! Problem while converting geom to grob. ℹ Error occurred in the 2nd layer.

Here a smal reproductive example of the error :

library(sf); library(maptiles)
library(tidyverse); library(scatterpie)

nc <- st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
nc_osm <- get_tiles(nc, crop = TRUE, zoom = 7)

dt_osm_i <- nc_osm %>%
  terra::as.data.frame(xy = TRUE)
names(dt_osm_i) <- c("x", "y", "red", "green", "blue")

dt_osm <- dt_osm_i %>%
  as_tibble() %>% 
  mutate(hex = rgb(red, green, blue, maxColorValue = 255)) 

pie = data.frame(
  lon=c(-82.5,-77,-80.5,-79), 
  lat=c(34,35,36,34.5), 
  A=c(0.25,0.75,0,0.25), 
  B=c(0.75,0.10,0,0.75), 
  C=c(0,0.15,1,0), 
  group=1,
  radius=0.05)

ggplot() +
  geom_tile(data= dt_osm, aes(x, y, fill = hex)) +
  scale_fill_identity() +
  geom_scatterpie(data = pie, mapping = aes(x = lon, y = lat, r = radius, group=group),
                  cols=c("A", "B", "C")) +
  theme_light() + xlab("") + ylab("")

Is anyone could solve this problem ? I am stuck with this in my work, if anyone could help me, it would be marvelous.

Versions: R version 4.4.0, ggplot2 version 3.5.1

Thanks a lot


Solution

  • Your issue is because scale_fill_identity() is being applied to both dt_osm and pie. The full error message:

    Error:
    ! Problem while converting geom to grob.
    ℹ Error occurred in the 2nd layer.
    Caused by error:
    ! Unknown colour name: A

    which tells you "A", "B", and "C" are being supplied as if they were R colour/hex values.

    To avoid this, you can use ggnewscale::new_scale_fill() to essentially 'turn off' scale_fill_identity() so that you can set a new fill scale:

    library(ggplot2)
    library(ggnewscale)
    library(scatterpie)
     
    ggplot() +
      geom_tile(data = dt_osm, aes(x, y, fill = hex)) +
      scale_fill_identity() +
      new_scale_fill() +
      geom_scatterpie(data = pie, 
                      aes(lon, lat, r = radius, group = group),
                      cols = c("A", "B", "C")) +
      theme_light() +
      xlab("") +
      ylab("")
    

    However, by converting your map tile object to a dataframe, the CRS is removed and data are plotted in Cartesian rather than geographic/projected coordinates. This will result in distortion of your tile object and your output plot will be sensitive to plot dimensions.

    To avoid this you can use tidyterra::geom_spatraster_rgb(). Note that the radius value in pie was changed to radius = .1 so that the pie charts were visible in the example output.

    library(ggplot2)
    library(tidyterra)
    library(scatterpie)
    
    ggplot() +
      geom_spatraster_rgb(data = nc_osm) +
      geom_scatterpie(data = pie, 
                      aes(x = lon, y = lat, r = radius, group=group),
                      cols=c("A", "B", "C")) +
      theme_light() + 
      xlab("") + 
      ylab("")
    

    1