Learn R Programming

ggsced

Utilities and helpers for Single-Case Experimental Design (SCED) using ggplot2

Overview

The ggsced package extends the powerful ggplot2 visualization framework to provide specialized tools for creating high-quality graphics for Single-Case Experimental Design (SCED) research. SCED studies are a crucial methodology in behavioral and educational research, where individual participants serve as their own controls through carefully designed experimental phases. This approaches rests on careful visual inspection of data presented in graphs that clearly delineate phase changes and patterns.

Purpose

Single-case experimental designs require specific visualization conventions that are not easily achieved with standard plotting approaches. The ggsced package bridges the gap between the flexibility of ggplot2 and the specific visualization needs of single-case researchers by providing:

  • Professional Phase Change Lines: Clear visual demarcation between experimental phases that meet publication standards
  • Multiple Baseline Design Support: Staggered intervention implementation across participants with precise phase change timing
  • Complex Data Pattern Visualization: Support for multiple dependent variables plotted simultaneously
  • Publication-Ready Graphics: APA and journal-compliant figures with consistent styling

Key Features

Core Visualization Functions

  • ggsced(): Primary function for adding phase change lines to existing ggplot objects
  • ggsced_style_x() and ggsced_style_y(): Styling functions for axes that follow SCED conventions with broken axis appearance

Design Pattern Support

  • Multiple Baseline Designs: Staggered intervention implementation across participants
  • Alternating Treatment Designs: Rapid alternation between different intervention conditions
  • Functional Analysis Designs: Multiple dependent variables with distinct visual markers
  • Complex Phase Patterns: Support for multiple intervention phases within studies

Professional Styling

  • Consistent Visual Standards: Publication-quality aesthetics with proper fonts and scaling
  • Broken Axis Convention: SCED-specific axis styling with disconnected x/y axes
  • Flexible Customization: Modular design allows adaptation to diverse research needs
  • Multi-panel Support: Seamless integration with ggplot2 faceting for participant comparisons

Installation

# Install from GitHub (development version)
# install.packages("devtools")
devtools::install_github("miyamot0/ggsced")

# Load the package
library(ggsced)

Quick Start

Example Multiple Baseline: Gilroy et al. (2015)

library(ggsced)
library(tidyverse)
library(ggh4x)

data <- Gilroyetal2021

y_mult = .05
x_mult = .02

p = ggplot(data, aes(Session, Responding,
                     group = Condition)) +

  geom_line() +
  geom_point(size = 2.5,
             pch = 21,
             fill = 'black') +

  geom_line(mapping = aes(Session, Reinforcers),
            lty = 2) +
  geom_point(mapping = aes(Session, Reinforcers),
             size = 2.5,
             pch = 24,
             fill = 'white') +
  scale_x_continuous(breaks = c(1:25),
                     limits = c(1, 25),
                     expand = expansion(mult = x_mult)) +
  facet_grid2(Participant ~ .,
              scales = "free_y",
              remove_labels = "x",
              axes = "x")  +
  facetted_pos_scales(
    y = list(
      scale_y_continuous(name = "Frequency",
                         breaks = c(0, 10, 20),
                         limits = c(0, 20),
                         expand = expansion(mult = y_mult)),
      scale_y_continuous(name = "Frequency",
                         breaks = c(0, 5, 10),
                         limits = c(0, 10),
                         expand = expansion(mult = y_mult)),
      scale_y_continuous(name = "Frequency",
                         breaks = c(0, 10, 20),
                         limits = c(0, 20),
                         expand = expansion(mult = y_mult))
    )
  ) +
  theme(
    text = element_text(size = 14,
                        color = 'black'),
    panel.background = element_blank(),
    strip.background = element_blank(),
    strip.text = element_blank()
  ) +
  ggsced_style_x(x_mult, lwd = 2) +
  ggsced_style_y(y_mult, lwd = 2)

simple_facet_labels_df = ggsced_facet_labels(p, y = 20)
simple_facet_labels_df[2, "Responding"] <- 10
simple_facet_labels_df[3, "Responding"] <- 8

p <- p + geom_text(data = simple_facet_labels_df,
                   hjust = 1,
                   vjust = 0.5,
                   mapping = aes(label = label))

simple_condition_labels_df = ggsced_condition_labels(p)
simple_condition_labels_df$label = gsub("2", "", simple_condition_labels_df$label)

p <- p + geom_text(data = simple_condition_labels_df,
                   mapping = aes(label = label),
                   hjust = 0.5,
                   vjust = 0.5)

# Create extra rows for Bx Labels
extra_labels_df <- simple_condition_labels_df[1:2,]
extra_labels_df$Session <- 21.25
extra_labels_df$x0 <- 21
extra_labels_df$x1 <- 19.5
extra_labels_df$y <- 15

extra_labels_df[1, "label"] <- 'Responding'
extra_labels_df[1, "Responding"] <- 15

extra_labels_df[2, "label"] <- 'Reinforcers'
extra_labels_df[2, "Responding"] <- 5
extra_labels_df[2, "y"] <- 5

p <- p + geom_text(data = extra_labels_df,
                   mapping = aes(label = label),
                   hjust = 0,
                   vjust = 0.5)

p <- p + geom_segment(data = extra_labels_df,
                      mapping = aes(x = x0,
                                    y,
                                    xend = x1,
                                    yend = y),
                      arrow = arrow(length = unit(0.25, "cm")))

staggered_pls = list(
  '1' = c(3.5,   3.5,   3.5),
  '2' = c(6.5,   6.5,   8.5),
  '3' = c(9.5,   9.5,  11.5),
  '4' = c(12.5,  16.5,  16.5),
  '5' = c(15.5,  22.5,  19.5)
)

offsets_pls = list(
  '1' = c(F, F, F),
  '2' = c(F, F, F),
  '3' = c(F, F, F),
  '4' = c(F, F, F),
  '5' = c(T, F, F)
)

ggsced(p, legs = staggered_pls, offs = offsets_pls)

Example Augmented Multiple Baseline: Gilroy et al. (2021)


library(ggsced)
library(tidyverse)
library(ggh4x)

data <- Gilroyetal2021

y_mult = .05
x_mult = .02

p = ggplot(data, aes(Session, Responding,
                     group = Condition)) +

  geom_line() +
  geom_point(size = 2.5,
             pch = 21,
             fill = 'black') +

  geom_line(mapping = aes(Session, Reinforcers),
            lty = 2) +
  geom_point(mapping = aes(Session, Reinforcers),
             size = 2.5,
             pch = 24,
             fill = 'white') +
  scale_x_continuous(breaks = c(1:25),
                     limits = c(1, 25),
                     expand = expansion(mult = x_mult)) +
  facet_grid2(Participant ~ .,
              scales = "free_y",
              remove_labels = "x",
              axes = "x")  +
  facetted_pos_scales(
    y = list(
      scale_y_continuous(name = "Frequency",
                         breaks = c(0, 10, 20),
                         limits = c(0, 20),
                         expand = expansion(mult = y_mult)),
      scale_y_continuous(name = "Frequency",
                         breaks = c(0, 5, 10),
                         limits = c(0, 10),
                         expand = expansion(mult = y_mult)),
      scale_y_continuous(name = "Frequency",
                         breaks = c(0, 10, 20),
                         limits = c(0, 20),
                         expand = expansion(mult = y_mult))
    )
  ) +
  theme(
    text = element_text(size = 14,
                        color = 'black'),
    panel.background = element_blank(),
    strip.background = element_blank(),
    strip.text = element_blank()
  ) +
  ggsced_style_x(x_mult, lwd = 2) +
  ggsced_style_y(y_mult, lwd = 2)

simple_facet_labels_df = ggsced_facet_labels(p, y = 20)
simple_facet_labels_df[2, "Responding"] <- 10
simple_facet_labels_df[3, "Responding"] <- 8

p <- p + geom_text(data = simple_facet_labels_df,
                   hjust = 1,
                   vjust = 0.5,
                   mapping = aes(label = label))

simple_condition_labels_df = ggsced_condition_labels(p)
simple_condition_labels_df$label = gsub("2", "", simple_condition_labels_df$label)

p <- p + geom_text(data = simple_condition_labels_df,
                   mapping = aes(label = label),
                   hjust = 0.5,
                   vjust = 0.5)

# Create extra rows for Bx Labels
extra_labels_df <- simple_condition_labels_df[1:2,]
extra_labels_df$Session <- 21.25
extra_labels_df$x0 <- 21
extra_labels_df$x1 <- 19.5
extra_labels_df$y <- 15

extra_labels_df[1, "label"] <- 'Responding'
extra_labels_df[1, "Responding"] <- 15

extra_labels_df[2, "label"] <- 'Reinforcers'
extra_labels_df[2, "Responding"] <- 5
extra_labels_df[2, "y"] <- 5

p <- p + geom_text(data = extra_labels_df,
                   mapping = aes(label = label),
                   hjust = 0,
                   vjust = 0.5)

p <- p + geom_segment(data = extra_labels_df,
                      mapping = aes(x = x0,
                                    y,
                                    xend = x1,
                                    yend = y),
                      arrow = arrow(length = unit(0.25, "cm")))

staggered_pls = list(
  '1' = c(3.5,   3.5,   3.5),
  '2' = c(6.5,   6.5,   8.5),
  '3' = c(9.5,   9.5,  11.5),
  '4' = c(12.5,  16.5,  16.5),
  '5' = c(15.5,  22.5,  19.5)
)

offsets_pls = list(
  '1' = c(F, F, F),
  '2' = c(F, F, F),
  '3' = c(F, F, F),
  '4' = c(F, F, F),
  '5' = c(T, F, F)
)

ggsced(p, legs = staggered_pls, offs = offsets_pls)

Other Example Datasets

The package includes several real research datasets for learning and demonstration:

  • Gilroyetal2015: Multiple baseline design data
  • Gilroyetal2021: Cross-lagged Alternating Treatment Design

Documentation

  • Comprehensive vignette: Detailed examples with real research data
  • Function documentation: Complete help files for all exported functions
  • Demo files: Executable examples in the demo/ directory
  • Test suite: Extensive testing to ensure reliability

Dependencies

  • ggplot2: Core plotting functionality
  • grid: Low-level graphics operations
  • gtable: Plot layout management
  • ggh4x: Extended ggplot2 functionality

Author and Contact

Shawn P. Gilroy, Ph.D.
Louisiana State University

Copy Link

Version

Install

install.packages('ggsced')

Version

0.1.6

License

GPL (>= 2)

Maintainer

Shawn Gilroy

Last Published

January 21st, 2026

Functions in ggsced (0.1.6)

ggsced_output_console

ggsced_output_console
ggsced_name_dogleg_lateral

ggsced_name_dogleg_lateral
sced_phase_change_complex_lateral_pre_grob

sced_phase_change_complex_lateral_pre_grob
sced_phase_change_complex_lateral_grob

sced_phase_change_complex_lateral_grob
ggsced_style_y

ggsced_style_y
ggsced_internal_x_axis

ggsced_internal_x_axis
ggsced_name_dogleg

ggsced_name_dogleg
ggsced_get_panels

ggsced_get_panels
ggsced_internal_y_axis

ggsced_internal_y_axis
ggsced

ggsced
ggsced_condition_labels

generate_condition_labels
Gilroyetal2015

Plotting data from Gilroy et al. (2015)
ggsced_extract_domain

ggsced_extract_domain
ggsced_scale_units

ggsced_scale_units
ggsced_style_x

ggsced_style_x
Gilroyetal2021

Plotting data from Gilroy et al. (2021)
sced_phase_change_complex_lateral_post_grob

sced_phase_change_complex_lateral_post_grob
ggsced_facet_labels

ggsced_facet_labels
sced_phase_change_simple_lateral_grob

sced_phase_change_simple_lateral_grob
sced_phase_change_main_panel_grob

sced_phase_change_main_panel_grob