ggside()
Published

August 7, 2025

Marginal Plot

A marginal plot is a visualization that combines a main plot (usually a scatter plot) with additional plots in the margins of the axes. These marginal plots display the distributions of the individual variables, often using histograms, box plots, or other visual representations.

library(ggalign)
#> Loading required package: ggplot2
#> 
#> Attaching package: 'ggalign'
#> The following object is masked from 'package:ggplot2':
#> 
#>     element_polygon
ggside(mpg, aes(displ, hwy, colour = class)) -
    scheme_theme(theme_bw()) +
    geom_point(size = 2) +
    # initialize top annotation
    anno_top(size = 0.3) +
    # add a plot in the top annotation
    ggalign() +
    geom_density(aes(displ, y = after_stat(density), colour = class), position = "stack") +
    # initialize right annotation
    anno_right(size = 0.3) +
    # add a plot in the right annotation
    ggalign() +
    geom_density(aes(x = after_stat(density), hwy, colour = class),
        position = "stack"
    )

Reproduce cases in Add marginal plots of ggpubr post.

ggside(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
    geom_point(size = 3, alpha = 0.6) +
    ggsci::scale_color_jco() +
    theme_classic() +
    anno_top(size = 0.2) +
    ggalign() +
    geom_density(aes(x = Sepal.Length)) +
    theme_no_axes() +
    anno_right(size = 0.2) +
    ggalign() +
    geom_density(aes(y = Sepal.Width)) +
    theme_no_axes()

ggside(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
    geom_point(size = 3, alpha = 0.6) +
    ggsci::scale_color_jco() +
    theme_classic() +
    anno_top(size = 0.2) +
    ggalign() +
    geom_boxplot(aes(x = Sepal.Length), fill = "grey") +
    theme_no_axes() +
    anno_right(size = 0.2) +
    ggalign() +
    geom_boxplot(aes(y = Sepal.Width), fill = "grey") +
    theme_no_axes()

ggside(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
    geom_point(size = 3, alpha = 0.6) +
    ggsci::scale_color_jco() +
    theme_light() +
    anno_top(size = 0.2) +
    ggalign() +
    geom_density(aes(x = Sepal.Length, fill = Species, alpha = 0.6)) +
    theme_no_axes() +
    anno_right(size = 0.2) +
    ggalign() +
    geom_density(aes(y = Sepal.Width, fill = Species), alpha = 0.6) +
    theme_no_axes() &
    ggsci::scale_fill_jco() &
    theme(legend.position = "none")

ggside(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
    geom_point(size = 3, alpha = 0.6) +
    geom_smooth(method = lm) +
    ggpubr::stat_cor() +
    ggsci::scale_color_jco() +
    theme_light() +
    anno_top(size = 0.2) +
    ggalign() +
    geom_density(aes(x = Sepal.Length, fill = Species, alpha = 0.6)) +
    theme_no_axes() +
    anno_right(size = 0.2) +
    ggalign() +
    geom_density(aes(y = Sepal.Width, fill = Species), alpha = 0.6) +
    theme_no_axes() &
    ggsci::scale_fill_jco() &
    theme(legend.position = "none")
#> `geom_smooth()` using formula = 'y ~ x'