# Drop constant columns from a CSV

Find and remove constant (zero-variance) columns from a CSV — columns with one repeated value or all blanks. In-browser, no upload.

## Run it

- **CLI:** `gizza tool constant-column-dropper "id,country,score,notes
1,US,10,
2,US,20,
3,US,30,
4,US,40,"`
- **Web:** https://gizza.ai/tools/constant-column-dropper/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/constant-column-dropper/tool.json

## Inputs

- `data` — CSV/table data _(field)_
- `header` — First row is a header _(field)_
- `delimiter` — Delimiter _(field)_
- `dominance` — Dominance threshold (%) _(field)_
- `empty_cells` — Empty cells _(field)_
- `ignore_case` — Ignore case _(field)_
- `ignore_whitespace` — Ignore whitespace _(field)_
- `keep` — Never drop these columns _(field)_
- `output` — Output _(field)_

## Output

- Constant column report (text)

## Query parameters

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

- `data` — CSV/table data
- `header` — First row is a header
- `delimiter` — Delimiter
- `dominance` — Dominance threshold (%)
- `empty_cells` — Empty cells
- `ignore_case` — Ignore case
- `ignore_whitespace` — Ignore whitespace
- `keep` — Never drop these columns
- `output` — Output

Example: `https://gizza.ai/tools/constant-column-dropper/?data=id%2Ccountry%2Cscore%2Cnotes%0A1%2CUS%2C10%2C%0A2%2CUS%2C20%2C%0A3%2CUS%2C30%2C%0A4%2CUS%2C40%2C&header=true&delimiter=comma&dominance=100&empty_cells=value&ignore_case=true&ignore_whitespace=true&keep=id%2C%20country&output=report`

---

## About this tool

**Constant Column Dropper** finds the **zero-variance columns** in a CSV or
delimited table — the ones that carry a single repeated value down every data
row, or that contain nothing at all — and removes them.

Constancy is measured as *one distinct value*, not as a statistical variance of
zero. That matters: the distinct-value rule works on text columns
(`country = US` in every row) as well as numbers, and it handles blank cells
without special-casing. Columns like this add no information to a model, a
pivot, or a report — they just make the table wider.

Set **Dominance** below 100 to also catch *near*-constant columns: at 95, a
column whose most common value covers 95% or more of the rows is flagged too.
Everything runs locally in your browser — your data is never uploaded.

### Worked example

Input:

```
id,country,score,notes
1,US,10,
2,US,20,
3,US,30,
4,US,40,
```

Default report:

```
Scanned 4 columns across 4 data rows (dominance 100%).
Found 2 constant columns; 2 columns remain.

Constant columns (dropped):
  "country" (col 2)  =  "US" in 4/4 rows (100%)
  "notes" (col 4)  =  all cells are empty

Use output=csv to get the table with those columns removed.
```

With **Output = Cleaned CSV**, the result is:

```
id,score
1,10
2,20
3,30
4,40
```

**JSON metrics** returns the same verdict per column plus the numbers behind it —
`distinct_values`, `top_value`, `top_count` and `top_share_percent` — so you can
script the decision instead of eyeballing it.

### Options

- **First row is a header** — on by default. The header row is excluded from the
  value counts and preserved in cleaned CSV output.
- **Delimiter** — comma, tab, semicolon, or pipe. Output uses the same one.
- **Dominance threshold** — 100 (default) drops only strictly constant columns.
  Lower it to drop near-constant ones: 95 means "at least 95% of the rows say the
  same thing". The range is 50–100.
- **Empty cells** — *Count as a value* (default) means a column of values plus
  blanks is not constant; *Skip when counting* ignores blanks first, so a column
  that is `gold`, blank, `gold` counts as constant. A column that is entirely
  empty is dropped either way.
- **Ignore case** — on by default, so a column of `YES` / `yes` counts as constant.
- **Ignore whitespace** — on by default, so `US` and ` US ` are the same value.
- **Never drop these columns** — comma-separated column names or 1-based column
  numbers to protect. A protected column stays in the output and is listed
  separately in the report.
- **Output** — human report, cleaned CSV, or JSON metrics.

### Limits and edge cases

- The last column standing is never removed silently: if *every* column would be
  dropped, **Cleaned CSV** returns an error naming the count instead of emitting
  an empty table. Switch to the report to see what happened, or protect a column.
- A column that is entirely empty is always dropped, whichever empty-cell mode is
  selected — there is no value in it to keep.
- Case and whitespace normalization affect the *comparison* only. Cells are
  written to the cleaned CSV exactly as you pasted them.
- Ragged rows are allowed: the table is as wide as its widest row, and missing
  cells are counted as empty.
- A header row alone, with no data rows, is an error — there is nothing to
  measure.
- This is a paste-sized page. Multi-hundred-megabyte files belong in a data
  pipeline, not a browser tab.

## FAQ

<details>
<summary>What exactly counts as a constant column?</summary>

A column whose data rows hold exactly one distinct value after the optional case
and whitespace normalization — or a column with no non-empty cells at all. That
is the same rule as `nunique() == 1` in a dataframe, or `min == max`, and unlike
a statistical variance test it works on text columns too.

</details>

<details>
<summary>How do I catch columns that are almost constant?</summary>

Lower the **Dominance threshold**. At 95, a column is dropped when its most
frequent value covers 95% or more of the counted rows — the "near-zero-variance"
case that feature-selection tools flag alongside true constants. The report
always shows the actual share, so you can see how close a call it was.

</details>

<details>
<summary>Does a blank cell count as a value?</summary>

Your choice. With **Empty cells = Count as a value** (the default) a column of
`gold`, blank, `gold` has two distinct values and survives. With **Skip when
counting**, blanks are removed first and the column reads as constant. Dataframe
tools differ on this, which is why it is a switch rather than a fixed rule.

</details>

<details>
<summary>Can I protect an ID or label column from being dropped?</summary>

Yes. List it under **Never drop these columns**, by header name or by 1-based
column number (`id, 3`). Protected columns stay in the cleaned CSV and are
reported separately, so you still learn that they were constant.

</details>

<details>
<summary>Is my table uploaded anywhere?</summary>

No. The tool is compiled to WebAssembly and runs entirely in your browser. Your
CSV/table data never leaves your device.

</details>

## Related tools

- [Prune highly correlated features](https://gizza.ai/tools/correlated-feature-pruner/): Drop multicollinear numeric columns by thresholded Pearson, Spearman, or Kendall correlation. In-browser, no upload.
- [CSV Column Splitter & Concatenator](https://gizza.ai/tools/csv-column-split/): Split a CSV column into multiple columns by delimiter, or concatenate columns into one. Header-aware, trim options, exact CSV output, in-browser.
- [CSV Dedupe](https://gizza.ai/tools/csv-dedupe/): Remove duplicate rows from a CSV, keeping the first — optionally keyed on chosen columns. Runs in your browser, nothing is uploaded, free.
- [Stepwise feature selection for regression](https://gizza.ai/tools/stepwise-feature-selection/): Run forward, backward, or bidirectional stepwise OLS regression on a numeric table to choose predictors by AIC, BIC, AICc, or p-value thresholds.
- [Absolute value, sign, or negation for a whole column](https://gizza.ai/tools/absolute-value-transformer/): Paste a column of numbers and apply absolute value, sign extraction (-1/0/1), sign flipping, or force-negative to every value at once, with rounding and an audit table.
