trevorld / ggpattern

ggplot geoms with pattern fills
https://trevorldavis.com/R/ggpattern/dev/
Other
356 stars 18 forks source link

[BUG] Problem using a transparent ggpattern in a geom_sf() layer #125

Closed binkleym closed 1 month ago

binkleym commented 1 month ago

Bug description

ggpattern appears to have an issue where ggpattern won't use a transparent background in geom_sf()

Minimal, reproducible example

Here is the NWS SPC's wind map: https://i.imgur.com/iDPBOMv.gif

Here is the result ggpattern produces: https://i.imgur.com/WZdv5vQ.png

Notice the area with the hatched pattern centered in Nebraska. In the SPC's version, the colored risk levels can be seen through the hatching.

Notice the same area rendered by ggpattern is mostly but not completely opague to the layers beneath it.

Notice

Please enter here a minimal, reproducible example of your bug. Thanks!

I wrote R code to render NWS SPC Wind maps: https://pastebin.com/2bmcfW5d

Session info

Please enter here the results of xfun::session_info("ggpattern")

R version 4.4.0 (2024-04-24) Platform: x86_64-pc-linux-gnu Running under: Ubuntu 22.04.4 LTS, RStudio 2023.9.1.494

Locale: LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C
LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

Package version: cachem_1.1.0 class_7.3.22 classInt_0.4.10 cli_3.6.2 colorspace_2.1.0 DBI_1.2.2
e1071_1.7.14 fansi_1.0.6 farver_2.1.2 fastmap_1.2.0 ggpattern_1.0.1 ggplot2_3.5.1
glue_1.7.0 graphics_4.4.0 grDevices_4.4.0 grid_4.4.0 gridpattern_1.2.1 gtable_0.3.5
isoband_0.2.7 KernSmooth_2.23.24 labeling_0.4.3 lattice_0.22.6 lifecycle_1.0.4 magrittr_2.0.3
MASS_7.3.60.2 Matrix_1.7.0 memoise_2.0.1 methods_4.4.0 mgcv_1.9.1 munsell_0.5.1
nlme_3.1.164 pillar_1.9.0 pkgconfig_2.0.3 png_0.1.8 proxy_0.4.27 R6_2.5.1
RColorBrewer_1.1.3 Rcpp_1.0.12 rlang_1.1.3 s2_1.1.6 scales_1.3.0 sf_1.0.16
splines_4.4.0 stats_4.4.0 tibble_3.2.1 tools_4.4.0 units_0.8.5 utf8_1.2.4
utils_4.4.0 vctrs_0.6.5 viridisLite_0.4.2 withr_3.0.0 wk_0.9.1

trevorld commented 1 month ago

Please come up with a minimal, reproducible example of your problem.

With a simple example I observe that geom_sf_pattern() does render a transparent background in my current graphics device ("X11cairo") i.e. the {ggplot2} gridlines are perfectly visible...:

library("ggpattern")
library("ggplot2")
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
indices <- which(nc$CNTY_ID >= 1820 & nc$CNTY_ID <= 1830)
nc <- nc[indices, ]

p <- ggplot(nc) +
  geom_sf_pattern(pattern = "crosshatch", fill = NA, pattern_spacing = 0.1,
                  pattern_aspect_ratio = 2.8
  ) +
  theme_bw(15) +
  theme(legend.key.size = unit(1.5, 'cm')) +
  labs(title = "ggpattern::geom_sf()")

p

image

binkleym commented 1 month ago

This is as minimal a code as I can make it.

library(dplyr)
library(ggplot2)
library(ggpattern)
library(sf)

map_wind <-
  read_sf("https://www.spc.noaa.gov/products/outlook/day1otlk_wind.kmz") %>%
  mutate(Name = ifelse(is.na(Name), "Sig", Name))

ggplot() +
    theme_bw() + 

    # Comment/uncomment this line to see the behavior change.
    geom_sf(data = map_wind, aes(fill = Name), color = NA, show.legend = TRUE) +

    geom_sf_pattern(data = map_wind %>% filter(Name == "Sig"), aes(pattern = Name), fill = NA, show.legend = TRUE, 
                    linewidth = 0.5, pattern_spacing = 0.1) +

    scale_fill_manual(
      limits = c("5 %",     "15 %",    "30 %",    "45 %",    "60 %",    "Sig"),
      values = c("#c5a393", "#ffeb80", "#ff8080", "#ff00ff", "#912cee", NA)
    ) + 
    scale_pattern_manual(
      limits = c("5 %",  "15 %", "30 %", "45 %", "60 %", "Sig"),
      values = c("none", "none", "none", "none", "none", "crosshatch")
  ) 

If the line is commented out, transparency works. You can see the grid through the pattern:

ex_0

But if you add the line back in and try to render the pattern over an existing geom_sf() object, transparency doesn't work. You can't see the yellow of the underlying geom_sf() through the pattern.

ex_1

trevorld commented 1 month ago

I don't get your point. If you comment out the geom_sf_pattern() the geom_sf() shows grey over yellow too... Isn't the transparent fill geom_sf_pattern() working exactly as you'd expect (not hiding the grey region from geom_sf())?

ggplot() +
    theme_bw() + 

    # Comment/uncomment this line to see the behavior change.
    geom_sf(data = map_wind, aes(fill = Name), color = NA, show.legend = TRUE) +

    # geom_sf_pattern(data = map_wind %>% filter(Name == "Sig"), aes(pattern = Name), fill = NA, show.legend = TRUE, 
    #               linewidth = 0.5, pattern_spacing = 0.1) +

    scale_fill_manual(
      limits = c("5 %",     "15 %",    "30 %",    "45 %",    "60 %",    "Sig"),
      values = c("#c5a393", "#ffeb80", "#ff8080", "#ff00ff", "#912cee", NA)
    ) + 
    scale_pattern_manual(
      limits = c("5 %",  "15 %", "30 %", "45 %", "60 %", "Sig"),
      values = c("none", "none", "none", "none", "none", "crosshatch")

image

binkleym commented 1 month ago

Thanks, that was a helpful reply. It appears that the problem isn't ggpattern, but ggplot or some other package/R functionality that's changed recently.

Here's how the graph should look:

ggpattern_transparency_bug

The problem appears to be that in the scale_fill_manual() where I am setting "Sig" to NA (which should render as transparent). It appears that instead of transparency, ggplot is putting a default color there instead.

So it's Someone Else's Problem and I apologize, but appreciate the assistance in working around it.

trevorld commented 1 month ago

I'd speculate using "transparent" instead of NA or explicitly setting the default NA value argument in scale_fill_manual() to "transparent" would work. Or any of the RGBA color strings with the alpha channel set to zero.

trevorld commented 1 month ago

According to git blame scale_fill_manual()'s na.value has been "grey50" for "3 years": https://github.com/tidyverse/ggplot2/blame/28aec3a90d2798382c7da384fece6227e12092f8/R/scale-manual.R#L92

So scale_fill_manual() changing NA to "grey50" has been "expected" behavior for "a while".