TSGap
A Python library for simulating realistic missingness in time-series data for imputation benchmarking.
TSGap separates mechanisms (why data is missing: MCAR, MAR, MNAR) from
patterns (how data is missing: pointwise, block, monotone, decay, markov,
Gilbert-Elliott).
Most patterns can be combined with any mechanism, making it easy to create
controlled missing-data scenarios for evaluating imputation methods.
gilbert_elliott is MCAR-only because it models an independent burst-loss
channel rather than value- or driver-dependent missingness.
Features
- MCAR, MAR, and MNAR missingness mechanisms
- Pointwise, block, monotone, temporal decay, Markov-chain, and Gilbert-Elliott patterns
- 2D
(time, features)and 3D(samples, time, features)arrays - Exact or calibrated missing-rate control
- Weighted multi-driver MAR
- Reproducible masks with NumPy random seeds
- Existing NaNs and target dimensions preserved across patterns
Installation
pip install tsgap
For development:
git clone https://github.com/feruzoripov/tsgap.git
cd tsgap
pip install -e ".[dev]"
Requires Python 3.9 or newer and NumPy 1.19 or newer.
Quick Start
import numpy as np
from tsgap import simulate_missingness
X = np.random.default_rng(42).standard_normal((1000, 6))
# MCAR: 15% scattered missing values
X_miss, mask = simulate_missingness(X, "mcar", 0.15, seed=42)
# MAR: missingness driven by dimension 0 and arranged in blocks
X_miss, mask = simulate_missingness(
X, "mar", 0.25, seed=42,
pattern="block", driver_dims=[0], block_len=10
)
# Scale block length to the sequence length for long series
# The default block pattern uses block_len=10 and block_density=1.0.
# block_frac is recommended
# for long wearable-style series where fixed 10-sample blocks are too short.
X_miss, mask = simulate_missingness(
X, "mcar", 0.20, seed=42,
pattern="block", block_frac=0.01
)
# Sample each block length between 1% and 5% of the time axis
X_miss, mask = simulate_missingness(
X, "mcar", 0.20, seed=42,
pattern="block", block_frac=(0.01, 0.05)
)
# MNAR: extreme values missing with monotone dropout
X_miss, mask = simulate_missingness(
X, "mnar", 0.20, seed=42,
pattern="monotone", mnar_mode="extreme"
)
# Gilbert-Elliott: bursty packet-loss with leaky good/bad periods.
# Burst length is controlled by `persist` (not block_frac): higher persist
# means longer bursts. `bad_loss` < 1 lets some values through during a bad
# period, and `good_loss` > 0 drops the occasional value during a good period.
X_miss, mask = simulate_missingness(
X, "mcar", 0.20, seed=42,
pattern="gilbert_elliott", persist=0.9,
bad_loss=0.8, good_loss=0.02
)
print(f"Actual missing rate: {(~mask).mean():.4f}")
The returned mask uses:
mask == True -> observed
mask == False -> missing
Documentation
- Installation
- Core concepts
- Mathematical details
- Mechanisms
- Patterns
- API reference
- Benchmarking workflow
Example Use Cases
- Random telemetry loss in sensor networks
- Activity-dependent dropout in wearable devices
- Participant dropout in longitudinal or clinical studies
- Gradual signal loss from sensor degradation
- Intermittent connectivity failures with bursty missingness
Evaluation Workflow
import numpy as np
from tsgap import simulate_missingness
X = np.random.default_rng(42).standard_normal((1000, 6))
X_miss, mask = simulate_missingness(X, "mar", 0.20, seed=42, driver_dims=[0])
X_imputed = your_imputation_method(X_miss)
missing_idx = ~mask
rmse = np.sqrt(np.mean((X[missing_idx] - X_imputed[missing_idx]) ** 2))
mae = np.mean(np.abs(X[missing_idx] - X_imputed[missing_idx]))
See docs/benchmarking.md for a complete baseline workflow.
The repository also includes a runnable benchmark example:
python examples/benchmark_imputation.py
Testing
pytest tsgap/tests/ -v
Citation
@software{tsgap,
author = {Oripov, Feruz and Korchagina, Kseniia and Bonsu, Enock Adu and Bilgin, Ali and Aras, Shravan},
title = {TSGap: A Python Library for Composable Time-Series Missingness Simulation},
year = {2026},
version = {0.7.0},
doi = {10.5281/zenodo.21365453},
url = {https://github.com/feruzoripov/tsgap}
}
License
MIT
Metadata
Release files for tsgap 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tsgap-0.7.0.tar.gz | 564.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tsgap-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 592.4 kB
Release files / tsgap-0.7.0.tar.gz
| Download URL | tsgap-0.7.0.tar.gz |
|---|---|
| Size | 564.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d0a7aa58ced192849f35f40fa20e85015b18f9574e02f633994271caffbee2c4
|
|
BLAKE2b-256 checksum How to use checksums |
6d989e9fa66818d11006d5c48c6877b4ad49fff1a4a736d928bd8f147f28b05e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Release files / tsgap-0.7.0-py3-none-any.whl
| Download URL | tsgap-0.7.0-py3-none-any.whl |
|---|---|
| Size | 27.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e424bf98cbe8675c3867f2850364eec4c098412eb90f7f852043020488919154
|
|
BLAKE2b-256 checksum How to use checksums |
97672ba71d12819f337910209aba7226ed8972482f1d695e3ad5de6928e95c1e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|