Search code examples
rggplot2ggrough

Unable to replicate this ggplot2 plot


I am unable to replicate an example from the ggrough library (https://xvrdm.github.io/ggrough/articles/Customize%20chart.html). In particular, I am trying to replicate the following plot (minus the font aspects):

enter image description here

The code is from the same link above under the "Kindergarten" header.

I am using the following code:

library(hrbrthemes)
library(tidyverse)
library(gcookbook)
library(ggplot2)
library(ggrough)
ggplot(uspopage, aes(x=Year, y=Thousands, fill=AgeGroup)) + 
    geom_area(alpha=0.8) +
    scale_fill_ipsum() +
    scale_x_continuous(expand=c(0,0)) +
    scale_y_comma() -> p 

options <- list(GeomArea=list(fill_style="hachure", 
                              angle_noise=0.5,
                              gap_noise=0.2,
                              gap=1.5,
                              fill_weight=1))
get_rough_chart(p, options)

However, I am unable to replicate the above. Here is what I get:

enter image description here

Again, I am not worried about the fonts, but do want to get the shaded geom_area to work. It currently doesn't render at all. For reference, here is what the p object yields (i.e., the plot before it goes through the ggrough processing):

enter image description here

Also note that I am able to replicate the "Blueprint" example, which uses geom_col. So it appears that something is going wrong with ggrough processing the geom_area, but not sure.


Solution

  • The ggrough package doesn't work well with the current version of ggplot2 for geom_area, because it looks for the target area in xml nodes bearing the name "polyline". In older versions of ggplot2, this probably worked fine, because each area was enclosed by a polyline. In more recent versions, however, this is no longer the case (see breaking changes under 3.3.0).

    See if the following works for you:

    1. Define a version of the parse_* function that look for "polygon", rather than "polyline".
    parse_polygons <- function (svg) {
      shape <- "polygon" # was "polyline" in ggrough:::parse_areas
      keys <- NULL
      ggrough:::parse_shape(svg, shape, keys) %>% {
        purrr::map(., 
                   ~purrr::list_modify(.x, 
                                       points = stringr::str_squish(.x$points) %>% 
                                         {stringr::str_glue("M{.}Z")}, 
                                       shape = "path"))
      }
    }
    
    1. Change the corresponding un-exported function in ggrough to use the newly defined parse_polygons for GeomArea layers.

    In addition, I've added in GeomRibbon (which appeared to be missing from the original but is really a more general case of GeomArea) & moved GeomViolin over from parse_areas to parse_polygons, because it faces the same issue.

    (Note: GeomSmooth will probably break too, but I think its parse function will take a bit more tweaking, compared to GeomRibbon / GeomViolin, & I'm not seeing a use case for it...)

    trace(ggrough:::parse_rough, edit = TRUE)
    
    # paste the following function into the pop-up window
    function (svg, geom) {
      rough_els <- list()
      if (geom %in% c("GeomCol", "GeomBar", "GeomTile", "Background")) {
        rough_els <- append(rough_els, parse_rects(svg))
      }
      if (geom %in% c("GeomSmooth", "Background")) {   # removed GeomArea / GeomViolin from here
        rough_els <- append(rough_els, parse_areas(svg))
      }
      if (geom %in% c("GeomArea", "GeomRibbon", "GeomViolin")) {  # new condition here
        rough_els <- append(rough_els, parse_polygons(svg))
      }
      if (geom %in% c("GeomPoint", "GeomJitter", "GeomDotPlot", "Background")) {
        rough_els <- append(rough_els, parse_circles(svg))
      }
      if (geom %in% c("GeomLine", "GeomSmooth", "Background")) {
        rough_els <- append(rough_els, parse_lines(svg))
      }
      if (geom %in% c("Background")) {
        rough_els <- append(rough_els, parse_texts(svg))
      }
      purrr::map(rough_els, ~purrr::list_modify(.x, geom = geom))
    }
    

    Test:

    library(ggplot2)
    library(ggrough)
    
    uspopage <- gcookbook::uspopage
    p <- ggplot(uspopage, aes(x=Year, y=Thousands, fill=AgeGroup)) + 
      geom_area(alpha=0.8) +
      scale_x_continuous(expand=c(0,0)); p
    options <- list(GeomArea=list(fill_style="hachure", 
                                  angle_noise=0.5,
                                  gap_noise=0.2,
                                  gap=1.5,
                                  fill_weight=1))
    get_rough_chart(p, options)
    

    geom_area plot

    Additional test for geom_ribbon:

    # using example from geom_ribbon help page
    pp <- data.frame(year = 1875:1972, level = as.vector(LakeHuron)) %>%
      ggplot(aes(year)) +
      geom_ribbon(aes(ymin = level - 1, ymax = level + 1), 
                  fill = "grey70")
    options <- list(GeomRibbon=list(fill_style="hachure", 
                                    angle_noise=0.5,
                                    gap_noise=0.2,
                                    gap=1.5,
                                    fill_weight=1))
    get_rough_chart(pp, options)
    

    geom_ribbon plot

    Session info:

    R version 4.0.1 (2020-06-06)
    Platform: x86_64-w64-mingw32/x64 (64-bit)
    Running under: Windows 10 x64 (build 15063)
    
    Matrix products: default
    
    locale:
    [1] LC_COLLATE=English_Singapore.1252  LC_CTYPE=English_Singapore.1252   
    [3] LC_MONETARY=English_Singapore.1252 LC_NUMERIC=C                      
    [5] LC_TIME=English_Singapore.1252    
    
    attached base packages:
    [1] stats     graphics  grDevices utils     datasets  methods   base     
    
    other attached packages:
    [1] gdtools_0.2.2 dplyr_1.0.0   ggrough_0.1.0 ggplot2_3.3.2
    
    loaded via a namespace (and not attached):
     [1] Rcpp_1.0.5        cpp11_0.2.1       pillar_1.4.6      compiler_4.0.1   
     [5] plyr_1.8.6        Rmisc_1.5         forcats_0.5.0     tools_4.0.1      
     [9] boot_1.3-25       digest_0.6.25     jsonlite_1.7.1    lifecycle_0.2.0  
    [13] tibble_3.0.3      gtable_0.3.0      lattice_0.20-41   pkgconfig_2.0.3  
    [17] rlang_0.4.7       rstudioapi_0.11   yaml_2.2.1        xml2_1.3.2       
    [21] withr_2.2.0       stringr_1.4.0     htmlwidgets_1.5.1 systemfonts_0.3.1
    [25] generics_0.0.2    vctrs_0.3.4       grid_4.0.1        tidyselect_1.1.0 
    [29] data.table_1.12.8 svglite_1.2.3.2   glue_1.4.2        R6_2.4.1         
    [33] gcookbook_2.0     tidyr_1.1.0       reshape2_1.4.4    purrr_0.3.4      
    [37] farver_2.0.3      magrittr_1.5      htmltools_0.5.0   scales_1.1.1     
    [41] ellipsis_0.3.1    fortunes_1.5-4    colorspace_1.4-1  labeling_0.3     
    [45] stringi_1.5.3     munsell_0.5.0     crayon_1.3.4