MyNixOS website logo
Description

Serpentine Plots for Long Timeline, Sequential and Survey Data.

Visualize long timelines, extended sequences and temporally chained survey responses and experience sampling data using intuitive serpentine (snake) plots. Supports distribution bars, tick-mark plots, inter-item correlation arcs, faceted multi-construct panels, and daily time-of-day positioning for ecological momentary assessment data.

snakeplot

License: MIT R-CMD-check Codecov Version Dependencies

Serpentine (snake) plots for survey responses, experience sampling (EMA/ESM) data, and activity timelines using base R graphics. Zero external dependencies.

Installation

# From GitHub.
devtools::install_github("mohsaqr/snakeplot")

# Once on CRAN
install.packages("snakeplot")

Overview

Snake plots arrange data as horizontal bands in a serpentine layout — each row reverses direction and connects to the next through a U-turn arc. The package provides six plotting functions and 10 built-in color palettes:

FunctionPurpose
survey_snake()Survey/EMA responses with ticks, bars, correlations, faceting
activity_snake()Daily activity timelines with event blocks or rug ticks
sequence_snake()State sequence as colored blocks flowing through serpentine layout
timeline_snake()Career/life-event timeline from a 3-column data.frame (role, start, end)
survey_sequence()Stacked 100% horizontal bars in serpentine layout
sequential_dist()Sequential (monochrome) variant of survey_sequence()
line_snake()Continuous intensity line plot (experimental)
facet_snake()Generic multi-panel wrapper for any snake function

Bundled datasets

Three datasets from Neubauer & Schmiedek (2024) are included:

DatasetRowsDescription
ema_emotions280Person-level means for 10 emotions (1-7 scale)
student_survey28034 items across 4 constructs, prefixed for faceting
ema_beeps11 474Beep-level timestamps + anger/happiness ratings (14 days)

Examples

library(snakeplot)

labs7 <- c("1" = "Not at all", "2" = "Slightly", "3" = "Somewhat",
           "4" = "Moderate",   "5" = "Quite",    "6" = "Very",
           "7" = "Extremely")

survey_snake() — daily value distribution ticks

survey_snake(ema_beeps, var = "angry", day = "day",
             colors = snake_palettes$ocean, level_labels = labs7,
             title = "Anger — 14 days, value distribution")

survey_snake() — correlation arcs

survey_snake(ema_emotions, tick_shape = "line",
             arc_fill = "correlation", sort_by = "mean",
             colors = snake_palettes$ocean, level_labels = labs7,
             title = "Emotions — correlations at U-turns")

survey_snake() — dot plot with dark bands

survey_snake(ema_emotions, tick_shape = "dot", sort_by = "mean",
             colors = snake_palettes$ocean, level_labels = labs7,
             band_palette = c("#1a1228", "#1a2a42"),
             title = "Emotions — dots on dark bands")

survey_snake() — faceted multi-construct

survey_snake(student_survey, facet = TRUE, facet_ncol = 2L,
             tick_shape = "bar", sort_by = "mean",
             colors = snake_palettes$ocean, level_labels = labs7)

survey_snake() — daily distribution bars

survey_snake(ema_beeps, var = "happy", day = "day",
             tick_shape = "bar", bar_reverse = TRUE,
             colors = snake_palettes$ocean, level_labels = labs7,
             title = "Happiness — 14 days, distribution bars")

activity_snake() — rug ticks

set.seed(42)
days <- c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
d <- data.frame(
  day      = rep(days, each = 40),
  start    = round(runif(280, 360, 1400)),
  duration = 0
)
activity_snake(d)

activity_snake() — duration blocks

d2 <- data.frame(
  day      = rep(days, each = 8),
  start    = round(runif(56, 360, 1200)),
  duration = round(runif(56, 15, 120))
)
activity_snake(d2, event_color = "#e09480", band_color = "#3d2518")

sequence_snake() — state sequence

set.seed(42)
verbs <- c("Read", "Write", "Discuss", "Listen",
           "Search", "Plan", "Code", "Review")
seq75 <- character(0)
while (length(seq75) < 75) {
  seq75 <- c(seq75, rep(sample(verbs, 1), sample(1:4, 1)))
}
seq75 <- seq75[seq_len(75)]
sequence_snake(seq75, title = "75-step learning sequence")

timeline_snake() — career/event timeline

career <- data.frame(
  role  = c("Intern", "Junior Dev", "Mid Dev",
            "Senior Dev", "Tech Lead", "Architect"),
  start = c("2015-01", "2015-07", "2017-01",
            "2019-07", "2022-07", "2024-01"),
  end   = c("2015-06", "2016-12", "2019-06",
            "2022-06", "2023-12", "2024-12")
)
timeline_snake(career,
               title = "Software Engineer — Career Path (2015-2024)")

survey_sequence() — stacked bars

survey_sequence(ema_emotions, colors = snake_palettes$ocean)

line_snake() — continuous intensity

set.seed(42)
hours <- seq(0, 1440, by = 10)
d_line <- data.frame(
  day   = rep(c("Mon", "Tue", "Wed", "Thu", "Fri"), each = length(hours)),
  time  = rep(hours, 5),
  value = sin(rep(hours, 5) / 1440 * 4 * pi) * 50 + 50 +
          rnorm(5 * length(hours), 0, 8)
)
line_snake(d_line, fill_color = "#e74c3c")

Built-in palettes

10 palettes ship with the package — 5 diverging, 5 sequential:

names(snake_palettes)
#> "classic" "earth" "ocean" "sunset" "berry" "blues" "greens" "grays" "warm" "viridis"

# Use directly
survey_snake(ema_emotions, colors = snake_palettes$earth, tick_shape = "bar")

# Interpolate to any length
snake_palette("sunset", n = 5)

Key parameters for survey_snake()

ParameterDescription
tick_shape"line" (default), "dot", or "bar" (stacked proportional)
sort_by"none", "mean", or "net"
arc_fill"none" (two-tone), "correlation", "mean_prev", "blend"
colorsCustom color palette or snake_palettes$name
band_palette2+ anchor colors for band shading (default: brown-to-slate)
bar_reverseTRUE to draw bars from highest level first
level_labelsNamed vector mapping levels to display labels
facetTRUE (auto-group by prefix) or named list of column groups
var, day, timestampAuto-pivot EMA data into daily bands
show_mean, show_medianToggle diamond/dashed-line markers

Data source

The bundled datasets are derived from:

Neubauer, A. B., & Schmiedek, F. (2024). Approaching academic adjustment on multiple time scales. Zeitschrift fuer Erziehungswissenschaft, 27(1), 147-168. https://doi.org/10.1007/s11618-023-01182-8

License

MIT.

Metadata

Version

0.3.0

License

Unknown

Platforms (78)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    uefi
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-uefi
  • aarch64-windows
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-linux
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-uefi
  • x86_64-windows