Search code examples
rggplot2patchwork

Patchwork doesn't recognize plots with ggMargnial distribution elements


Trying to display 2 plots with ggMarginal but the plots are not recognized as such.

I'm pasting a simplified version of the code below where:

  • Before adding the ggMarginal element Patchwork displays ggplots side by side as expected
  • After adding marginal distributions with ggMarginal, Patchwork doesn't seem to recognize the the plot any more. The error message that I get is the following:
p1m + p2m
#> Error in p1m + p2m: non-numeric argument to binary operator

Here's the code I'm running:

library(ggplot2)
library(ggExtra)
library(patchwork)

p1 <- ggplot(mtcars) + 
  geom_point(aes(mpg, disp)) + 
  ggtitle('Plot 1')

p1m <- ggMarginal(p1,
                 type = "density",
                 size = 3)

p2 <- ggplot(mtcars) + 
  geom_point(aes(hp, wt, colour = mpg)) + 
  ggtitle('Plot 3')

p2m <- ggMarginal(p2,
                 type = "density",
                 size = 3)

p1+p2



p1m + p2m
#> Error in p1m + p2m: non-numeric argument to binary operator

Thanks a lot for your help!

Created on 2021-10-09 by the reprex package (v2.0.1)


Solution

  • Not sure whether there is an easy option to make patchwork work with objects of class ggMarginal.

    Another option to add side plots would be to make use of the ggside package which works fine with patchwork. One drawback of ggside is that (to the best of my knowledge) as of the moment it does not offer any options to style the side plots, i.e. it will inherit the style of the main plot's theme:

    library(ggplot2)
    library(ggside)
    #> Registered S3 method overwritten by 'ggside':
    #>   method from   
    #>   +.gg   ggplot2
    library(patchwork)
    
    p1 <- ggplot(mtcars, aes(mpg, disp)) + 
      geom_point() + 
      geom_xsidedensity(aes(y = after_stat(density)), position = "stack") +
      geom_ysidedensity(aes(x = after_stat(density)), position = "stack") +
      ggtitle('Plot 1')  +
      theme(ggside.panel.scale = .5)
    
    p2 <- ggplot(mtcars, aes(hp, wt, colour = mpg)) + 
      geom_point() + 
      geom_xsidedensity(aes(y = after_stat(density)), position = "stack") +
      geom_ysidedensity(aes(x = after_stat(density)), position = "stack") +
      ggtitle('Plot 3') +
      theme(ggside.panel.scale = .5,)
    
    p1 + p2
    

    A second but cumbersome option would be to make the marginal plots via ggplot2 too and glue all together using patchwork:

    p1 <- ggplot(mtcars) + 
      geom_point(aes(mpg, disp)) + 
      ggtitle('Plot 1')
    
    p2 <- ggplot(mtcars) + 
      geom_point(aes(mpg, disp, colour = mpg)) + 
      ggtitle('Plot 3')
    
    p1ma <- ggplot(mtcars) + 
      geom_density(aes(mpg)) + 
      theme_void()
    
    p1mb <- ggplot(mtcars) + 
      geom_density(aes(y = disp)) + 
      theme_void()
    
    wrap_plots(list(p1ma, plot_spacer(), p1ma, plot_spacer(), p1, p1mb, p2, p1mb), 
               widths = c(2, 1, 2, 1), heights = c(1, 2),
               ncol = 4, nrow = 2, byrow = TRUE) &
      theme(legend.position = "bottom")