Blank Plot Output when using "geom_xspline" in ggalt package

650 Views Asked by At

When trying to use geom_xspline from ggalt in conjunction with ggarrange from ggpubr, the output is blank and no other plot can be made before clearing with dev.off().

In my use-case I wanted the geom_xspline to replace some exisitng geom_line in my ggplot object. Is anyone aware of issues using geoms added from other R packages?

Here is some code to compare, nothing of interest really, just to give a reproducible example:

Initial Working Code w/o geom_xspline

library(ggplot2)
library(ggpubr)
myplot = ggplot(data = mtcars, aes(x = wt, y = mpg)) +
geom_line()
ggarrange(myplot, myplot) # Works and outputs fine

Code that fails with ggalt package

library(ggalt)
library(ggplot2)
library(ggpubr)
myplot = ggplot(data = mtcars, aes(x = wt, y = mpg)) +
geom_xspline()
ggarrange(myplot, myplot) # Output becomes blank and freezes the plot panel

Alternative Method Instead of using ggarrange I tried the function grid_arrange_shared_legend from this link, which uses grid and gridExtra. However, I am still curious as to why ggarrange does not work.

Here is my session info:

R version 3.5.1 (2018-07-02)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggpubr_0.1.8  magrittr_1.5  ggplot2_3.0.0

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.18       pillar_1.3.0       compiler_3.5.1     RColorBrewer_1.1-2 plyr_1.8.4         bindr_0.1.1       
 [7] tools_3.5.1        extrafont_0.17     tibble_1.4.2       gtable_0.2.0       pkgconfig_2.0.1    rlang_0.2.1       
[13] rstudioapi_0.7     yaml_2.2.0         bindrcpp_0.2.2     Rttf2pt1_1.3.7     withr_2.1.2        dplyr_0.7.6       
[19] maps_3.3.0         grid_3.5.1         ggalt_0.4.0        tidyselect_0.2.4   cowplot_0.9.3      glue_1.3.0        
[25] R6_2.2.2           purrr_0.2.5        extrafontdb_1.0    scales_1.0.0       MASS_7.3-50        assertthat_0.2.0  
[31] proj4_1.0-8        colorspace_1.3-2   labeling_0.3       KernSmooth_2.23-15 ash_1.0-15         lazyeval_0.2.1    
[37] munsell_0.5.0      crayon_1.3.4

Quick addition, if I convert the object to a ggplotGrob(), it will work with ggarrange, but it will fail when I attempt to use common.legend = T.

2

There are 2 best solutions below

0
On BEST ANSWER

The xspline function, upon whichgeom_xspline is based, typically automatically plots using graphics. This led the ggalt package authors to find a few work-arounds to ensure it would play nicely with ggplot. My rough solutions both involve creating or adjusting a geom or stat from ggplot without using xspline. This makes it easier to use without a lot of pre-processing the data prior to ingesting with ggplot.

(1) New stat using splines

Using spline for interpolation of points instead of xspline.

# Create a new stat (adjusted from ggalt GitHub page)
stat_spline <- function(mapping = NULL, data = NULL, geom = "line",
                         position = "identity", na.rm = TRUE, show.legend = NA, inherit.aes = TRUE,
                         n=200, method = "fmm", ...) { # Just picking a rough default for n
  layer(
    stat = StatSpline,
    data = data,
    mapping = mapping,
    geom = geom,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(n=n,
                  method=method,
                  na.rm = na.rm,
                  ...
    )
  )
}

StatSpline <- ggproto("StatSpline", Stat,

                       required_aes = c("x", "y"),

                       compute_group = function(self, data, scales, params,
                                                n=200, method = "fmm") {

                         tmp <- spline(data$x, data$y, n = n, method = method, ties = mean)

                         data.frame(x=tmp$x, y=tmp$y)
                       }

)

# Plot with ggarrange
myplot = ggplot(data = mtcars, aes(x = wt, y = mpg)) +
stat_spline(mapping = aes(x = wt, y = mpg)) +
geom_point()

ggpubr::ggarrange(myplot, myplot)

This method isn't ideal if you want splines similar to Catmull-Rom instead of Cubic; you can see some large bends between control points.

enter image description here

(2) New geom using xsplineGrob

This is a slightly adjusted version of geom_xspline2 from ggalt

# Create new geom based upon code from ggalt GitHub page
GeomXSpline3 <- ggproto("GeomXSpline3", Geom,
                        required_aes = c("x", "y"),
                        default_aes = aes(colour = "black", shape=-1, open=T),
                        draw_key = draw_key_point,

                        draw_panel = function(data, panel_params, coord) {
                          coords <- coord$transform(data, panel_params)
                          grid::xsplineGrob(
                            coords$x, coords$y,
                            shape = coords$shape, 
                            open = coords$open[1],
                            gp = grid::gpar(col = coords$colour)
                          )
                        }
)

geom_xspline3 <- function(mapping = NULL, data = NULL, stat = "identity",
                          position = "identity", na.rm = FALSE, show.legend = NA,
                          inherit.aes = TRUE, ...) {
  layer(
    geom = GeomXSpline3, mapping = mapping,  data = data, stat = stat,
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}

# Plot with ggarrange
myplot = ggplot(data = mtcars, aes(x = wt, y = mpg)) +
  geom_xspline3(shape = -.25) + geom_point()
ggpubr::ggarrange(myplot, myplot) 

There were a couple issues with ensuring the shape parameter still accepted inputs between -1 and 1, however, this seems to be working okay now with ggarrange.

enter image description here

I used the following resources while writing this solution:

2
On

Well I am not sure why ggpubr::ggarrange causes failure of Plots pannel when used with ggalt::geom_xspline but I can tell you that plots are still getting created but just now shown on the plot pannel.

So it seems that using those together causes failure in the graphing device and it is only happening for ggalt::geom_xspline and not all the geoms in . That is a so you are on the right track posting to GitHub.

You can check that by running the code below:

library(ggalt)
library(ggplot2)
library(ggpubr)


myplot = ggplot(data = mtcars, aes(x = wt, y = mpg)) +
  geom_xspline()
myplot

g <- ggarrange(myplot, myplot) # Output becomes blank and freezes the plot panel
g

jpeg('rplot.jpg')
g
dev.off()
#> pdf 
#>   3

Created on 2019-05-30 by the reprex package (v0.3.0)

And this is the saved plot:

enter image description here