Metadata-Version: 2.5
Name: safesplit
Version: 0.3.0
Summary: Leakage-safe train/test splits: group-aware, time-aware, de-duplicated.
Project-URL: Homepage, https://github.com/happyhellpt/safesplit
Project-URL: Repository, https://github.com/happyhellpt/safesplit
Project-URL: Issues, https://github.com/happyhellpt/safesplit/issues
Author: Joel Gomes
License-Expression: AGPL-3.0-or-later
License-File: LICENSE
Keywords: cross-validation,data-leakage,data-quality,machine-learning,train-test-split
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Requires-Dist: numpy>=1.20
Requires-Dist: pandas>=1.3
Description-Content-Type: text/markdown

# 🔒 safesplit

[![PyPI](https://img.shields.io/pypi/v/safesplit)](https://pypi.org/project/safesplit/) [![Tests](https://github.com/happyhellpt/safesplit/actions/workflows/tests.yml/badge.svg)](https://github.com/happyhellpt/safesplit/actions/workflows/tests.yml) [![Python](https://img.shields.io/pypi/pyversions/safesplit)](https://pypi.org/project/safesplit/) [![License: AGPL v3](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)

**Leakage-safe train/test splits — group-aware, time-aware, de-duplicated.**

`sklearn.train_test_split` shuffles rows at random. For a lot of real data that
quietly leaks: the same patient lands on both sides, a time series trains on its
own future, or duplicate rows sit in train *and* test. Your score looks great
and isn't real.

`safesplit` gives you one honest split:

```python
pip install safesplit
```

```python
from safesplit import safe_split

# a group is never on both sides
train, test = safe_split(df, group_col="patient_id")

# train on the past, test on the future
train, test = safe_split(df, time_col="date")

# keep near-homologous protein/DNA sequences together
train, test = safe_split(df, seq_col="sequence")

# plain random split, but exact duplicates are dropped first
train, test = safe_split(df, test_size=0.2)
```

## What it does

| You pass | What you get |
|---|---|
| `group_col` | every group (patient / user / device) stays entirely on one side |
| `seq_col` | protein/DNA sequences that are *similar* stay on one side (homology-safe) |
| `time_col` | a chronological split — train is the past, test is the future |
| `dedupe=True` (default) | exact duplicate rows are removed before splitting |
| nothing extra | a reproducible random split |

## The companion to LeakHound

`safesplit` **prevents** the leaks that
[LeakHound](https://github.com/happyhellpt/leakhound) **detects**. Split with one,
verify with the other:

```python
from safesplit import safe_split
from leakhound import audit           # pip install leakhound-ml

train, test = safe_split(df, group_col="patient_id")
assert audit(train, test, group_col="patient_id").clean
```

## License

GNU AGPL-3.0-or-later © 2026 Joel Gomes. A commercial license is available if the
copyleft terms don't fit your use — open an issue.
