The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

flexsynth

R-CMD-check Lifecycle: experimental License: MIT

Flexible synthetic data for nested, longitudinal and linked multi-table data.

flexsynth generates utility-oriented synthetic data for supported flat, nested, longitudinal, and tree-linked structures, working natively in long format — no pivoting nested or longitudinal data to wide. It has first-class support for tree-linked multi-table data (e.g. patients → admissions → procedures / labs / meds), with referential integrity preserved by construction.

It ships two engines behind one interface:

Synthetic data is not anonymisation, and Track A output must never be described as differentially private.

Features

Installation

# install.packages("remotes")
remotes::install_github("lauyeehow1986-hub/Flexsynth")

The package installs with base-R dependencies. The default method = "cart" requires the suggested rpart package; ranger / partykit unlock additional tree methods, and data.table unlocks the row-binding fast-path. Use method = "sample" when only base R is available.

Quick start

Single nested / longitudinal table

library(flexsynth)

df <- data.frame(
  id    = rep(1:20, each = 2),
  visit = rep(1:2, times = 20),
  age   = rep(round(rnorm(20, 60, 8)), each = 2),
  sbp   = round(rnorm(40, 130, 15))
)

res <- synth(df, structure = ~ id / visit, method = "cart", seed = 1)
head(as.data.frame(res))

Multiple linked tables, synthesised jointly

patients <- data.frame(id = 1:50, sex = sample(c("F", "M"), 50, TRUE))
adm <- do.call(rbind, lapply(patients$id, function(pid) {
  n <- 1 + rpois(1, 0.6)
  data.frame(id = pid, admission_id = seq_len(n), los = 1L + rpois(n, 3))
}))

res <- synth_linked(
  tables     = list(patients = patients, admissions = adm),
  structures = list(patients   = ~ id,
                    admissions = ~ id / admission_id),
  keys       = list(patients   = "id",
                    admissions = c("id", "admission_id")),
  seed = 1
)
syn <- as.list(res)
check_linkage(syn, keys = list(patients = "id",
                               admissions = c("id", "admission_id")))

Diagnostics and disclosure risk

syn <- as.data.frame(synth(df, structure = ~ id / visit, seed = 1))
analysis_vars <- c("age", "sbp")             # exclude generated structure keys
d <- diagnose(real = df, syn = syn, vars = analysis_vars)
plot(d)                                  # overlaid marginals
disclosure_risk(real = df, syn = syn, quasi = analysis_vars)

Pooled inference from synthetic data

# Analyse all m synthetic sets with a published fully-synthetic pooling rule.
# A single set analysed naively generally under-states synthesis uncertainty.
res <- synth(df, structure = ~ id / visit, m = 10, seed = 1)
synth_glm(res, sbp ~ age)                 # pooled linear model
# any estimator works via pool_synth(res, function(d) <fit returning coef/vcov>)

Opt into differential privacy (Track B)

dp <- dp_control(epsilon = 1, delta = 1e-6, mechanism = "gaussian",
                 bounds = list(visit = c(1, 2), age = c(18, 100), sbp = c(60, 240)))
dp_res <- synth(df, structure = ~ id, privacy = dp, seed = 1)
dp_res$privacy                           # the (ε, δ) accounting record

Track B supports three release shapes:

dp_control() also exposes privately learned domains, cross-table conditioning, higher-order transitions, adaptive marginal selection, Private-PGM reconciliation, and AIM-style models. These controls trade statistical fidelity, cell sparsity, runtime, and privacy budget; they are not universally beneficial.

A governed DP release requires more than setting epsilon: define the privacy unit and public domain assumptions, justify contribution caps, retain the accounting record, review utility at the intended analysis grain, and obtain independent privacy review. See vignette("differential-privacy") for the supported combinations, accounting model, and limitations.

Learn more

Data & privacy

Bundled example datasets are fully synthetic cardiac data (see data-raw/make_toy_cardiac.R). No real patient data ships with this package, and none should ever be committed.

License

MIT © 2026 flexsynth authors

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.