license: cc0-1.0
pretty_name: Structural Causal Model Environment Pairs with Mechanism Drift Labels
size_categories:
- 100K<n<1M
task_categories: - tabular-classification
tags: - causal-inference
- structural-causal-model
- distribution-shift
- mechanism-shift
- synthetic
- tabular
configs: - config_name: cases
data_files: data/cases.csv - config_name: observations
data_files: data/observations.csv
Structural Causal Model Environment Pairs with Mechanism Drift Labels
Paired-environment structural causal model (SCM) data with ground-truth labels for which
structural mechanism changed between two environments — plus the deterministic generator
that produces it.
Fully synthetic. No external data of any kind: nothing downloaded, scraped, purchased, or
derived from any existing corpus, dataset or benchmark. No large language model output
appears in the data, the labels, the graphs or the identifiers. Every value is produced bynumpy from a supplied seed.
What a case contains
- a random directed acyclic graph over 10 variables (at most 3 parents per node),
- a reference environment sample and a current environment sample,
- ground truth naming, for every node, whether its structural equation changed and which
parameter changed: an incoming coefficient, the intercept, or the noise scale.
Each node follows
X_j = b_j + SUM_i ( W[j][i] * X_i ) + SUM_i ( nl[j][i] * tanh(X_i) ) + eps_j
Noise is Gaussian, or Student-t on a minority of nodes. Nonlinear parent terms and heavy
tails are identical in both environments and are never interventions — they exist so the
exact parametric family cannot simply be assumed.
Node labels v01–v10 are permuted independently per case, and columns are emitted in that
permuted order, so node identity carries no information across cases.
Why the data is interesting
A changed mechanism and a changed distribution are not the same thing. When a node's
structural equation is altered the change propagates downstream, so every descendant of an
intervened node also shows a different marginal distribution while its own equation is
untouched — on average about 4 such "pure descendants" per case.
Marginal two-sample testing therefore flags the innocent nodes. Recovering the intervened set
requires reasoning conditionally on each node's parents. That gap is the point of the
data.
Files
| File | Rows | Description |
|---|---|---|
data/cases.csv |
600 | one row per case |
data/observations.csv |
110,814 | long format, one row per (case, environment, observation) |
data/generation_config.json |
— | every parameter used, including the seed for this instance |
Join on case_id.
cases.csv
| Column | Type | Description |
|---|---|---|
case_id |
string | opaque case identifier, cm_ + 16 hex characters |
n_rows |
int | observations in each environment (50–140) |
graph_edges |
string | DAG as pipe-separated parent>child, e.g. v03>v07|v08>v02 |
drift_regime |
categorical | intervention magnitude: clear, contested, knife_edge |
shift_code |
string | label, 10 chars over {N,C,I,Z}; char i describes node v(i+1) |
n_shift |
int | number of intervened nodes (1–3) |
n_pure_descendants |
int | nodes downstream of an intervention that were not themselves intervened on |
ancestrally_coupled |
int | 1 if one intervened node is a descendant of another |
shift_code alphabet: N unchanged · C coefficient changed · I intercept changed ·Z noise scale changed.
observations.csv
| Column | Type | Description |
|---|---|---|
case_id |
string | joins to cases.csv |
environment |
categorical | ref or cur |
obs_index |
int | row index within the (case, environment) block |
v01 … v10 |
float | observed values, rounded to 4 decimals |
Generating more data
python generate_dataset.py --seed 12345 --cases 5200 --out ./my_data
--seed and --out are required; there is no default seed. Generation is fully
deterministic: the same seed reproduces both CSVs byte for byte (verified by SHA-256). All
randomness flows through numpy.random.default_rng — no global random state, no wall-clock,
no network. Requires only numpy and pandas.
Scope of the included instance
The instance in data/ is a 600-case reference sample generated with the published seed12345, provided so the schema, distributions and data shape can be inspected directly.
This repository is the canonical source and generator for this dataset family. Larger
instances — including any used for evaluation or benchmarking — are produced by the same
generator under a different seed.
Evaluation instances deliberately do not publish their seed. The seed reproduces both the
labels and the case_id values exactly, so publishing a generator together with an
evaluation instance's seed would publish that instance's answer key. If you build a benchmark
from this generator, keep its seed private.
Licence
CC0-1.0 (Creative Commons Zero v1.0 Universal) — public domain dedication, applying to
everything in this repository: the generator code and the data. There is no second licence
and no dual-licensing. Commercial use, redistribution and modification are unrestricted,
with no attribution requirement. Full text in LICENSE.
Citation
Structural Causal Model Environment Pairs with Mechanism Drift Labels.
Original synthetic data and generator. CC0-1.0.