Author: Robin Denz
SPMD is a small R Package implementing the Symmetric Pair
Matching Design (SPMD). Briefly, SPMD is a self-controlled
method that allows estimation of the causal effect of a possible
re-current binary exposure on a possible re-current event. It is similar
in spirit to the famous self-controlled case series (SCCS) design in the
sense that it is bi-directional, using both time before and after
exposures as controls (irrespective of events). However, unlike the SCCS
method, it not only automatically adjusts for time-invariant
confounders, but also automatically adjusts for all time-effects,
without requiring any assumptions on the functional form of these time
effects.
It does so by creating pairs of individuals, in which each individual acts as a control for the other individual at their respective exposure time. It can be shown that under mild assumptions of multiplicative effects and no interactions, both individual-level effects and time effects cancel out perfectly. For more details, please consult the associated paper (Denz et al. 2026).
This package is not finished. It is still under active development, so
breaking changes may occur at any time without warning. The
developmental version may be installed from github using the remotes
R-Package:
library(remotes)
remotes::install_github("RobinDenz1/SPMD")If you encounter any bugs or have any specific feature requests, please file an Issue.
Suppose we have data that looks like this:
library(data.table)
library(SPMD)
set.seed(1234)
data <- sim_example_data(n=500)
head(data)
#> Key: <.id, start>
#> .id start stop X A Y
#> <int> <num> <num> <num> <lgcl> <lgcl>
#> 1: 1 0 249 -1.2070657 FALSE FALSE
#> 2: 1 249 289 -1.2070657 TRUE FALSE
#> 3: 1 289 1000 -1.2070657 FALSE FALSE
#> 4: 2 0 221 0.2774292 FALSE FALSE
#> 5: 2 221 261 0.2774292 TRUE FALSE
#> 6: 2 261 623 0.2774292 FALSE TRUEThis is a simple simulated dataset. Here, A is the time-dependent
exposure and Y is the outcome. The probability for both exposure and
outcome are time-dependent, thus making time itself a sort of
confounder. In addition, X is a time-fixed confounder. Suppose though,
that X was unmeasured. If we want to estimate the causal effect of A
on Y adjusting for both, we could use:
spmd <- sym_pair_matching(Surv(start, stop, Y) ~ A, data=data,
id=".id", risk_period=40, pairs="all",
estimator="moments", bootstrap=TRUE)
summary(spmd)
#> ──────────────────────────────────────────────────────────────
#> Symmetric Pair Matching Design
#> ──────────────────────────────────────────────────────────────
#> Design
#> Risk period 40
#> Pairing strategy All possible pairs
#> Estimator Estimating equations
#>
#> Sample
#> Individuals 500
#> Exposed individuals 339
#> Exposure episodes 339
#> Individuals with >=1 event 339
#> Exposed + event 339
#> Symmetric pairs 49,247
#> Observation time used 96.57%
#>
#> Effect estimate
#> log(RR) RR SE 95% CI P-value
#> 0.899 2.457 0.542 1.596 – 3.718 0.001
#>
#> Bootstrap: 1,000 replicates
#>
#> Estimation
#> Estimating equation: exp{1/2 log(489 / 81)}
#> |A_n| / |E_n|^2: 0.0118183
#> ──────────────────────────────────────────────────────────────The true effect is 2.5 (see ?sim_example_data), so the estimate is
actually very close.
If you use this package, please cite the associated article:
Denz, Robin, Filippo Saatkamp, Katharina Meiszl and Nina Timmesfeld (2026). “The Symmetric Pair Matching Design: A Self-Controlled Method with Automatic Adjustment for Time Effects”. arXiv Preprint. doi: 10.48550/arXiv.2608.25979.
© 2026 Robin Denz
The contents of this repository are distributed under the GNU General Public License. You can find the full text of this License in this github repository. Alternatively, see http://www.gnu.org/licenses/.
