Additional ggplot things..

Combining Plots using {Patchwork}

Patchwork

Patchwork is the easiest way to combine ggplot objects.

# setup
library(tidyverse)
library(patchwork)

dat <- gapminder::gapminder
plot1 <- dat %>% 
  ggplot(aes(lifeExp, gdpPercap, colour = continent)) +
  geom_point(alpha = 0.5) +
  scale_y_continuous(trans = "log10") 

plot1

plot2 <- dat %>% 
  ggplot(aes(year, lifeExp, colour = continent)) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = "lm")

plot2

plot3 <- dat %>% 
  ggplot(aes(pop, continent, colour = continent)) +
  ggbeeswarm::geom_quasirandom(orientation = "y") +
  scale_x_log10()

plot3

Adding plots with + puts them side by side

plot1 + plot2

dividing plots with /puts them beneath each other

plot1 / plot2

Create groups of plots by using parentheses:

(plot1 + plot2) / plot3

This is nice, but we need to a few more things

combined_plots <- (plot1 + plot2) / plot3 +
  plot_layout(guides = "collect")

combined_plots

Try again, with just one legend

plot1 <- plot1 + guides(colour = "none")
plot2 <- plot2 + guides(colour = "none")

combined_plots <- (plot1 + plot2) / plot3 +
  plot_layout(guides = "collect")

combined_plots

You can do global changes to all ggplot elements using the & operator

combined_plots & 
  theme_light() &
  theme(legend.position = "top") &
  scale_fill_brewer(palette = "Dark2") &
  scale_colour_brewer(palette = "Dark2") 

Finally, control layouts and add annotations

combined_plots +
  plot_layout(guides = "collect", 
              heights = c(0.6, 0.4)) +
  plot_annotation(
    title = "This is already a pretty neat arrangement",
    subtitle = "Wow, look at them plots",
    caption = "Your APA ready caption goes here..",
    tag_levels = "A",
    tag_prefix = "(",
    tag_suffix = ")"
  ) & 
  theme_light() &
  theme(legend.position = "bottom",
        plot.caption = element_text(hjust=0)) &
  scale_fill_brewer(palette = "Dark2") &
  scale_colour_brewer(palette = "Dark2") 

Patchwork can also inset plots

plot3 <- plot3 +
  guides(colour = "none") +
  labs(y = "") +
  scale_x_log10(labels = scales::label_log(), 
                name = "Population")

plot1 +
  # get the legend back in
  guides(colour = "legend") +
  
  # make some room
  coord_cartesian(xlim = c(15, 90),
                  ylim = c(150,1e6)) +
  
  # inset the plot
  inset_element(
    plot3,
    left = 0.01,
    right = 0.45,
    top = 0.99,
    bottom = 0.45
    )  &
  theme_bw() &
  theme(legend.position = "bottom",
        plot.caption = element_text(hjust=0)) &
  scale_fill_brewer(palette = "Dark2") &
  scale_colour_brewer(palette = "Dark2") 

Raincloud Plots

I love raincloud plots, so I have to shout them out here! They are unfortunately a bit tricky to create, and only work for some data types (real continuous data, not likert type data).

But to just give some inspiration.

There’s several ways to create raincloud plots. The easiest is probably via the ggrain package:

library(ggrain)

ggplot(iris, aes(Species, Sepal.Length, fill = Species)) + 
    geom_rain() +
  coord_flip()

But it’s also possible with the ggdist and gghalves packages. See this great blog post by Cedric Scherer

Plotting Models

Several packages produce amazing plots that can go right in your papers :)

Here’s a couple of recommendations.

The {ggstatsplot} package

{ggstatsplot} is amazing for plotting relatively simple tests (t-tests, ANOVA, simple correlations).

The default can look a bit unwieldy at times, but the plots can be highly customized.

library(ggstatsplot)
# the default ANOVA
iris %>% 
  ggstatsplot::ggbetweenstats(Species, Sepal.Length)

{ggstatsplot} - ANOVA

# changing things is super easy, as ggstatsplot outputs a ggplot object
iris %>% 
  ggstatsplot::ggbetweenstats(Species, Sepal.Length) +
  ggsci::scale_color_jama() +
  labs(title = "My new title!",
       y = "Sepal length (mm)") +
  theme_light(base_size = 14) +
  theme(legend.position = "none")

{ggstatsplot} - Correlation

iris %>% 
  ggstatsplot::ggscatterstats(Sepal.Length, Sepal.Width, 
                              bf.message = FALSE)

{ggstatsplot} - model parameters

mod <- lm(formula = mpg ~ cyl * am, data = mtcars)

# creating a plot
p <- ggcoefstats(mod)
p

using {ggstatsplot} for model parameters

Not great for more complex models

# predicting life expectancy in gapminder data
my_model <- lme4::lmer(lifeExp ~ gdpPercap_log + year0 * continent + (1+year0|country),
                       data = dat %>% mutate(year0 = year - 1952,
                                             gdpPercap_log = log10(gdpPercap)),
                       control = lme4::lmerControl(optimizer = "bobyqa"))
ggcoefstats(my_model, effects = "fixed", sort = "ascending")

The {sjPlot} package

sjPlot is an amazing package that is particularly nice for plotting complexer models.

my_model %>% sjPlot::plot_model()

my_model %>% sjPlot::plot_model(type = "pred", terms = c("year0", "continent"))

The {sjPlot} package

my_model %>% sjPlot::plot_model(type = "pred", terms = c("year0", "continent")) +
  scale_x_continuous(labels = \(x) x + 1952) +
  theme_light() +
  theme(legend.position = "top") +
  labs(x = "year",
       y = "Life Expectancy",
       title = "Predicted life expectancy for different continents",
       subtitle = "Model: lifeExp ~ gdpPercap_log + year0 * continent + (1 + year0 | country)")

The {Dotwhisker} package

Also used by some people…

library(dotwhisker)

dotwhisker::dwplot(my_model)

What are you favorite packages to plot models?

Modelsummary

Modelplot from {modelsummary} can produce nice comparison plots from a set of models. Just provide a list of models to compare.

library(modelsummary)
modelplot(list("model 1" = my_model, 
               "model 2" = my_model))