Synthetic Multivariate Data Generator using Gaussian Copulas
Project description
SymPG — Synthetic Multivariate Data Generator
SymPG generates simulated datasets with arbitrary marginal distributions and a user-specified correlation structure, using the Gaussian copula approach. This was originally developed for DNA-methylation (CpG) data simulation.
SymPG is a lightweight, high-performance Python package for generating synthetic multivariate tabular data using a Gaussian Copula framework.
It allows researchers and data scientists to simulate complex datasets where variables have drastically different distribution shapes (like highly skewed Beta distributions or bimodal mixtures) while enforcing precise, user-defined rank (Spearman) correlations between them.
Key Features
- Flexible Marginal Distributions: Seamlessly map variables to standard SciPy distributions, custom functions, or complex bimodal mixture models.
- Block-Diagonal Grid Simulation: Easily generate massive "wide" datasets testing every combination of variables across multiple correlation levels in one vectorized shot.
- Positive-Definite Repair: Automatically repairs intended correlation matrices that lose positive-definiteness.
- Automated Metadata: Automatically tracks variables, generated parameters, and both intended vs. observed pairwise correlations.
Installation
Install SymPG via pip:
pip install sympg
Requires Python 3.8+ and depends on numpy, pandas, scipy, and scikit-learn.
Quickstart Tutorial
This tutorial demonstrates how to simulate a dataset with three drastically different variable shapes (a heavily skewed Beta, a standard Normal, and a bimodal Mixture) while forcing them to correlate with one another at $r=0.5$.
1. Define your distributions
You can define variables using simple strings, dictionaries with custom parameters, or pass SciPy distribution objects directly.
import sympg
from scipy.stats import norm
distributions = [
# 1. A highly skewed beta distribution (e.g., modeling DNA methylation)
dict(name="skewed", type="beta", a=9.8, b=430.2),
# 2. A standard normal control
"normal",
# 3. A custom bimodal mixture model
dict(
name="bimodal.mix",
type="mixture",
submodels=[norm(loc=0.2, scale=0.05), norm(loc=0.8, scale=0.05)],
weights=[0.5, 0.5]
)
]
2. Define one or more correlation scenarios
correlations=[0.01, 0.5, 0.9] # The intended Spearman correlation for all pairs
3. Run the simulation grid
Use simulate_grid to generate the data. By passing [0.5] as the correlation, SymPG will force every pair of these variables to correlate at 0.5. You can also pass a list like [0.1, 0.5, 0.9] to instantly generate multiple distinct correlation blocks.
# Generate 1,000 observations
dnam = sympg.simulate_grid(
distributions=distributions,
correlations=correlations,
n_obs=1000,
random_state=42
)
# Extract the generated Pandas DataFrame
data = dnam['data']
print(data.head())
4. Analyze the generated data
Even though the variables have completely different geometric shapes, SymPG's Gaussian copula ensures the underlying rank correlations remain robust.
# Check the observed Spearman correlation between the skewed beta and the mixture
observed_corr = data['skewed0'].corr(data['bimodal.mix0'], method='spearman')
print(f"Observed Spearman Correlation: {observed_corr:.3f}")
# Output: Observed Spearman Correlation: 0.46
5. Access Metadata
SymPG automatically tracks the configuration of your simulation, including the exact parameters used and the discrepancy between intended and observed correlations.
metadata_corr = dnam['meta']['corr']
print(metadata_corr.head())
Why use SymPG?
When training Machine Learning models (like Lasso or Ridge regression), passing variables with vastly different non-linear shapes causes linear Pearson correlations to collapse, forcing the model to severely underestimate the true association coefficients.
SymPG allows you to explicitly simulate these non-linear shape mismatches in a controlled environment, making it an invaluable tool for benchmarking feature engineering pipelines (like Quantile Normal Transformations) and testing the robustness of predictive models against complex real-world data.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License
How it works
- Draw correlated standard-normal samples using the target correlation matrix (Cholesky decomposition).
- Map each column to [0,1] via the normal CDF (probability integral transform).
- Apply the inverse CDF of the desired marginal distribution to each column.
This preserves the rank correlation structure while allowing any marginal shape.
Multiple distribution sets
Pass a list of lists to sweep both distribution types and correlation levels:
Single dataset
single = sympg.simulate(
distributions=["normal", dict(name="beta", a=2, b=5)],
correlations=[0.7], # one pair → one value
n_obs=1000,
var_names=["x", "y"],
random_state=1,
)
Built-in distributions
| Key | Scipy basis | Key parameters |
|---|---|---|
normal |
scipy.stats.norm |
loc, scale |
beta |
scipy.stats.beta |
a, b |
gamma |
scipy.stats.gamma |
a, scale |
gamma_norm |
scipy.stats.gamma (min–max normalised) |
a, scale |
lognormal |
scipy.stats.lognorm |
s, scale |
uniform |
scipy.stats.uniform |
low, high |
truncnorm |
scipy.stats.truncnorm |
a, b, loc, scale |
mixture |
custom mixture of 3 normal distributions |
Custom callables are also accepted: f(uniform_samples: np.ndarray) -> np.ndarray.
Diagnostics helpers
# Observed correlation summary across all scenarios
corr_summary = sympg.summarise_correlations(df, var_names=["phenotype", "CpG1", "CpG2"])
Saving results
df.to_csv("simulated_grid.csv", index=False)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sympg-0.1.1.tar.gz.
File metadata
- Download URL: sympg-0.1.1.tar.gz
- Upload date:
- Size: 17.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d90c83122219ce30e4cab51c08f04a8529ee96d2a82cad660cd87cac8b7c7657
|
|
| MD5 |
303ee300565da99ac8b4cb07e4b072f3
|
|
| BLAKE2b-256 |
45b26cdc01d98729a2892888205d616934f2f207bc481c569ee8dcb6963477a8
|
Provenance
The following attestation bundles were made for sympg-0.1.1.tar.gz:
Publisher:
release.yml on SereDef/sympg
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sympg-0.1.1.tar.gz -
Subject digest:
d90c83122219ce30e4cab51c08f04a8529ee96d2a82cad660cd87cac8b7c7657 - Sigstore transparency entry: 1370657585
- Sigstore integration time:
-
Permalink:
SereDef/sympg@54d52b272c82e537d652c05836cde75b6c86a85a -
Branch / Tag:
refs/tags/0.1.1 - Owner: https://github.com/SereDef
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@54d52b272c82e537d652c05836cde75b6c86a85a -
Trigger Event:
release
-
Statement type:
File details
Details for the file sympg-0.1.1-py3-none-any.whl.
File metadata
- Download URL: sympg-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
657b6626bcc9e65f6502face7c9fb84dd064f9fa28f247864a104bcc8f38e315
|
|
| MD5 |
c797051a7564732455f71524ef503568
|
|
| BLAKE2b-256 |
37d9f7378672b4f4bc6949d4e06ebe1d1db99c866e73abb0c14db2ec280f13bc
|
Provenance
The following attestation bundles were made for sympg-0.1.1-py3-none-any.whl:
Publisher:
release.yml on SereDef/sympg
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sympg-0.1.1-py3-none-any.whl -
Subject digest:
657b6626bcc9e65f6502face7c9fb84dd064f9fa28f247864a104bcc8f38e315 - Sigstore transparency entry: 1370657853
- Sigstore integration time:
-
Permalink:
SereDef/sympg@54d52b272c82e537d652c05836cde75b6c86a85a -
Branch / Tag:
refs/tags/0.1.1 - Owner: https://github.com/SereDef
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@54d52b272c82e537d652c05836cde75b6c86a85a -
Trigger Event:
release
-
Statement type: