rqaem is an R port of the eye-movement
recurrence-quantification-analysis method introduced by Anderson,
Bischof, Laidlaw, Risko and Kingstone (2013). It computes the
recurrence matrix and all the scalar metrics described in the paper
(rec, det, revdet, lam, tt, corm, meanline, maxline,
ent, relent, clusters), and ports the reference Python
implementation at bit-for-bit parity on the bundled test
fixtures.
On top of that it adds three things the originals don't have:
- a tidy data-frame workflow —
rqa_by()consumes long-format fixation data and returns a one-row-per-group tibble, - sparse storage for long fixation sequences (
Matrix::dgCMatrixfromn = 64upward), and - bootstrap significance testing and a radius-sweep helper for choosing a working radius (Fig. 7 of the 2013 paper).
# install.packages("devtools")
devtools::install_github("nccanderson/rqaem")library(rqaem)
# A short scanpath (16 fixations from the originals' TestRqa.py example).
fix <- tibble::tibble(
x = c(510, 466, 406, 135, 296, 117, 317, 439,
302, 444, 507, 341, 459, 493, 630, 655),
y = c(385, 429, 449, 333, 409, 398, 327, 305,
270, 347, 454, 327, 270, 293, 341, 431)
)
result <- rqa(fix, radius = 64)
result
#> <rqa_result> (rqa)
#> n = 16, radius = 64, line_length = 2, min_cluster = 8
#> Metrics:
#> nrec 9
#> rec 7.5
#> det 66.67
#> revdet NA
#> meanline 2
#> maxline 2
#> ent 0
#> relent NaN
#> lam 5.882
#> tt 2
#> corm 23.7
#> clusters 0The recurrence matrix is on result$recmat. Plot it directly:
plot_recurrence(result)The headline ergonomic win over the originals: feed rqa_by() a
long-format data frame and get back one row per trial with all 13
scalar metrics.
set.seed(1)
eyedat <- data.frame(
trial = rep(1:4, each = 25),
x = runif(100, 0, 1000),
y = runif(100, 0, 1000)
)
rqa_by(eyedat, x = x, y = y, by = "trial", radius = 80)
#> # A tibble: 4 x 14
#> trial n nrec rec det revdet meanline maxline ent relent lam tt
#> <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 25 6 2 NA NA NA NA NA NA NA NA
#> 2 2 25 3 1 NA NA NA NA NA NA NA NA
#> 3 3 25 8 2.67 NA NA NA NA NA NA NA NA
#> 4 4 25 5 1.67 NA NA NA NA NA NA NA NA
#> # i 2 more variables: corm <dbl>, clusters <dbl>rqa_bootstrap() builds a null distribution by resampling. Two null
types: "shuffle" (permute fixation order, preserve positions —
breaks temporal structure) and "uniform" (draw fresh fixations from
a uniform-on-screen distribution — breaks spatial structure too).
boot <- rqa_bootstrap(fix, radius = 64, n = 199, seed = 1L)
summary(boot)
#> <rqa_bootstrap> summary (shuffle, n = 199, 95% CI)
#> metric observed p_value lo hi
#> rec 7.500 1.00000 7.500 7.50
#> det 66.667 0.02041 22.222 55.56
#> lam 5.882 1.00000 5.882 17.65
#> tt 2.000 1.00000 2.000 2.50
#> corm 23.704 0.95918 21.037 51.85
#> ent 0.000 1.00000 0.000 0.00radius_sweep() runs rqa() over a grid of candidate radii and
optionally attaches a bootstrap-baseline ribbon. The companion
autoplot() method reproduces the radius-selection plot from the
paper:
sweep <- radius_sweep(fix, radii = c(30, 60, 90, 120, 150),
bootstrap_n = 99L, seed = 1L)
ggplot2::autoplot(sweep)
#> Warning: Removed 3 rows containing missing values or values outside the scale range
#> (`geom_ribbon()`).
#> Warning: Removed 3 rows containing missing values or values outside the scale range
#> (`geom_line()`).
#> Removed 3 rows containing missing values or values outside the scale range
#> (`geom_line()`).
#> Warning: Removed 3 rows containing missing values or values outside the scale range
#> (`geom_point()`).Anderson, N. C., Bischof, W. F., Laidlaw, K. E. W., Risko, E. F., & Kingstone, A. (2013). Recurrence quantification analysis of eye movements. Behavior Research Methods, 45(3), 842-856. https://doi.org/10.3758/s13428-012-0299-5
The reference Python and MATLAB implementations were written by
Walter F. Bischof and are bundled under rqa_original/ in this
repository's workspace.

