# Train/Test Split

Split a CSV into train, test and validation sets. Stratify on a label, keep groups together, or split sequentially for time series — with a reproducible seed.

## Run it

- **CLI:** `gizza tool train-test-split "id,label
1,a
2,b
3,a
4,b
5,a
6,b
7,a
8,b
9,a
10,b"`
- **Web:** https://gizza.ai/tools/train-test-split/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/train-test-split/tool.json

## Inputs

- `data` — CSV data _(field)_
- `test_size` — Test size (fraction below 1, row count from 1) _(field)_
- `validation_size` — Validation size (0 = no validation set) _(field)_
- `stratify_column` — Stratify column (keep class balance) _(field)_
- `stratify_bins` — Stratify bins for a numeric column (0 = use raw values) _(field)_
- `group_column` — Group column (keep matching rows in one split) _(field)_
- `shuffle` — Shuffle rows before splitting _(field)_
- `seed` — Random seed _(field)_
- `header` — First row is a header _(field)_
- `delimiter` — Delimiter _(field)_
- `output` — Output _(field)_

## Output

- Splits (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `data` — CSV data
- `test_size` — Test size (fraction below 1, row count from 1)
- `validation_size` — Validation size (0 = no validation set)
- `stratify_column` — Stratify column (keep class balance)
- `stratify_bins` — Stratify bins for a numeric column (0 = use raw values)
- `group_column` — Group column (keep matching rows in one split)
- `shuffle` — Shuffle rows before splitting
- `seed` — Random seed
- `header` — First row is a header
- `delimiter` — Delimiter
- `output` — Output

Example: `https://gizza.ai/tools/train-test-split/?data=id%2Clabel%0A1%2Ca%0A2%2Cb%0A3%2Ca%0A4%2Cb%0A5%2Ca%0A6%2Cb%0A7%2Ca%0A8%2Cb%0A9%2Ca%0A10%2Cb&test_size=0.2&validation_size=0&stratify_column=label&stratify_bins=0&group_column=patient&shuffle=true&seed=42&header=true&delimiter=comma&output=sections`

---

## About this tool

Use this browser-local CSV splitter to create reproducible train, test and optional validation sets for machine-learning experiments. Paste a CSV, choose a test size as either a fraction (`0.2`) or an absolute row count (`50`), and the tool returns labelled CSV sections, one selected split, a summary table, or JSON containing every split.

The default is an 80/20 train/test split with `seed = 42`, so the same CSV and settings always produce the same rows. Rows keep their original order inside each output split, which makes the result easier to inspect and diff.

You can stratify on a label column to keep class balance across splits, quantile-bin a numeric stratification column, group related rows so they never leak across train and test, or turn shuffling off for a sequential time-series split where the newest rows land in the test set.

## Worked example

Input:

```csv
id,label
1,a
2,b
3,a
4,b
5,a
6,b
7,a
8,b
9,a
10,b
```

With `test_size = 0.2`, `validation_size = 0`, `shuffle = false`, and `output = sections`, the rows are split sequentially:

```text
# train (8 rows)
id,label
1,a
2,b
3,a
4,b
5,a
6,b
7,a
8,b

# test (2 rows)
id,label
9,a
10,b
```

For a stratified split, keep `shuffle` on and set `stratify_column = label`. For a leakage-safe grouped split, leave `stratify_column` empty and set `group_column` to a patient, user, document, or other group identifier.

## Limits and edge cases

- `test_size` and `validation_size` below `1` are fractions of the data rows; values `1` or above are rounded to row counts.
- The split must leave at least one training row. If test plus validation consumes every row, the tool returns an error.
- `stratify_column` and `group_column` are mutually exclusive. Stratification balances classes; grouping prevents leakage, and combining both would imply a more complex grouped-stratified algorithm.
- Stratification requires `shuffle = true`. Turn shuffle off only for a sequential or time-series split.
- Grouped splits keep each group intact, so row counts can land near the requested sizes rather than exactly on them when groups are large.
- CSV input is parsed in memory. Convert Excel or Parquet to CSV first, and use a local script for very large datasets that do not fit comfortably in the browser.

## FAQ

<details>
<summary>Should I enter `0.2` or `20` for a 20% test split?</summary>

Use `0.2`. Numbers below `1` are treated as fractions of the data rows. A value of `20` means exactly twenty rows, not twenty percent.

</details>

<details>
<summary>How do I make the split reproducible?</summary>

Keep the same input CSV, the same settings, and the same `seed`. The default seed is `42`, so results are reproducible even if you never change the seed field.

</details>

<details>
<summary>When should I use stratify instead of group?</summary>

Use `stratify_column` when you want each split to preserve a label distribution, such as positive and negative classes. Use `group_column` when related rows must stay together, such as visits from the same patient or records from the same user. The tool requires you to choose one because the semantics are different.

</details>

<details>
<summary>How do I split time-series data?</summary>

Turn `shuffle` off. The tool then uses a sequential split: training rows come first, optional validation rows follow, and the test set gets the last rows.

</details>

## Related tools

- [Extract Action Items from Meeting Notes](https://gizza.ai/tools/action-item-extractor/): Extract action items, owners, and decisions from meeting notes or daily notes with deterministic rules. Markdown checklist or JSON, private in-browser.
- [Add Line Numbers](https://gizza.ai/tools/add-line-numbers/): Add line numbers to every line of text online, like nl or cat -n — custom start, step, separator, and alignment. Free and private, runs in your browser.
- [ANSI Log Renderer](https://gizza.ai/tools/ansi-log-renderer/): Paste ANSI-colored terminal output or CI logs and render them as HTML, or strip escape codes to plain text. Handles 16-color, 256-color, and truecolor SGR codes.
- [API response diff](https://gizza.ai/tools/api-response-diff/): Compare two JSON API responses and see only the meaningful changes: ignore request ids, timestamps and UUIDs, match arrays by key or as sets, export a JSON Patch.
- [Rust AST Diff](https://gizza.ai/tools/ast-diff/): Compare two Rust source snippets structurally. The tool parses both files, canonicalizes their ASTs, and ignores formatting, whitespace, and comments.
