ggplotting power curves from the simr package

The R package ‘simr’ has greatly facilitated power analysis for mixed-effects models using Monte Carlo simulation (which involves running hundreds or thousands of tests under slight variations of the data). The powerCurve function is used to estimate the statistical power for various sample sizes in one go. Since the tests are run serially, they can take a VERY long time; approximately, the time it takes to run the model supplied once (say, a few hours) times the number of simulations (nsim, which should be higher than 200), and times the number of different sample sizes examined. While there isn’t a built-in parallel method, the power curves for different sample sizes can be run separately, and the results can be progressively combined as each component finishes running (see tutorial). The power curves produced by simr are so good they deserve ‘ggplot2’ rendering. So, here’s a function for it.

Copy
# Plot power curve. This function plots the output from simr::powerCurve()
# or from combine_powercurve_chunks()
powercurvePlot = function( powercurve,
# Format interactions
interaction_symbol_x = TRUE,
# Value(s) to which the X axis should be expanded
x_axis_expand = NULL,
# Approximate number of X-axis levels
number_x_axis_levels = NULL ) {
# Load required packages
require(dplyr) # data wrangling
require(stringr) # text processing
require(simr) # used for summary()
require(ggplot2) # plotting
require(ggtext) # enable more formats and HTML code in plot title (×)
require(Cairo) # plot format
plot =
data.frame(summary(powercurve)) %>%
ggplot(aes(y = mean, x = nlevels, ymin = lower, ymax = upper, label = nlevels)) +
geom_ribbon(fill = 'grey94') + geom_errorbar(colour = 'grey40') + geom_point() +
# Print sample size by each point
# geom_label(colour = 'grey30', fill = 'white', alpha = .5,
# nudge_x = 5, nudge_y = -0.03, label.size = NA) +
# Draw 80% threshold
geom_hline(yintercept = 0.8, color = 'gray70', lty = 2) +
scale_y_continuous(name = 'Power', limits = c(0, 1),
breaks = c(0, .2, .4, .6, .8, 1),
labels = c('0%', '20%', '40%', '60%', '80%', '100%')) +
scale_x_continuous(n.breaks = number_x_axis_levels) +
expand_limits(x = x_axis_expand) + labs(x = 'Number of participants') +
theme_bw() +
theme(axis.title.x = element_text(size = 10, margin = margin(t = 8)),
axis.title.y = element_text(size = 10, margin = margin(r = 7)),
axis.text = element_text(size = 9),
axis.ticks = element_line(colour = 'grey50'),
plot.title = element_textbox_simple(size = 10, width = unit(1, 'npc'),
halign = 0.5, lineheight = 1.6,
padding = margin(5, 5, 5, 5),
margin = margin(0, 0, 1, 0),
r = grid::unit(8, 'pt'),
linetype = 1, fill = 'grey98',
box.colour = 'grey80'),
axis.line = element_line(colour = 'black'),
panel.border = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank())
# Plot title, conditional on replacement of colons in the names
# of interactions.
# (1) If interaction_symbol_x = TRUE
if(interaction_symbol_x) {
plot = plot +
# Display name of predictor alone in title instead of default label from 'simr'
ggtitle(powercurve$text %>%
str_remove("Power for predictor ") %>%
# Remove single quotation marks at the beginning and at the end
str_remove_all("^'|'$") %>%
# Replace interaction colons with times symbols
str_replace(':', ' × '))
# (2) If interaction_symbol_x = FALSE
} else {
plot = plot +
# Display name of predictor alone in title instead of default label from 'simr'
ggtitle(powercurve$text %>%
str_remove("Power for predictor ") %>%
# Remove single quotation marks at the beginning and at the end
str_remove_all("^'|'$"))
}
# Output
plot
}
view raw powercurvePlot.R delivered with ❤ by emgithub

A usage example

Hide
library(lme4)
library(simr)
library(ggplot2)

# Toy model with data from 'simr' package
fit = lmer(y ~ x + (x | g), data = simdata)

# Extend sample size of `g`
fit_extended_g = extend(fit, along = 'g', n = 12)

fit_powercurve = 
  powerCurve(fit_extended_g, fixed('x'), 
             along = 'g', breaks = c(4, 6, 8, 10, 12), 
             nsim = 50, seed = 123, progress = FALSE)

# Read in custom function to ggplot results from simr::powerCurve

source('https://raw.githubusercontent.com/pablobernabeu/powercurvePlot/main/powercurvePlot.R')

powercurvePlot(fit_powercurve, number_x_axis_levels = 6) +
  
  # Change some defaults
  
  xlab("Number of levels in 'g'") +
  
  theme(plot.title = element_blank(),
        axis.title.x = element_text(size = 18), 
        axis.title.y = element_text(size = 18), 
        axis.text = element_text(size = 17))