CSV Null Standardizer

Turn every flavour of "no data" — NA, N/A, NULL, NaN, a bare dash, an empty cell — into the one token you actually want, without touching your real values.

Try:
Standardized CSV

About this tool

Open enough real CSV exports and you will find the same column expressing "no data" four different ways: an empty cell here, NA there, #N/A from a spreadsheet, null from a database dump, and a lone - typed by whoever maintained the sheet by hand. Every downstream step then needs its own list of exceptions — a na_values= argument, a CASE WHEN in the load script, a find-and-replace before the import.

This tool collapses all of that into one rule. Paste the table, pick the single representation you want, and every cell that means "missing" is rewritten to it. Everything else is left exactly as it was: real values are copied byte-for-byte (padding included), the header row is never touched, quoted fields keep their quoting, ragged rows keep their length, and the field separator round-trips unchanged.

It standardizes the token, not the data. Nothing is guessed, averaged, or filled in — if you need means, medians, or nearest-neighbour fills, that is imputation and a different job. If you first want to know how much is missing and where, profile the table before you normalize it.

Worked example

Input (delimiter comma, replace with NULL, defaults everywhere else):

id,score,notes
1,42,ok
2,NA,
3,null,-
4,n/a,NaN

Output:

id,score,notes
1,42,ok
2,NULL,NULL
3,NULL,NULL
4,NULL,NULL

Note what did not change: the header stays id,score,notes even though a header cell could match a token, and 42/ok are untouched. n/a matched N/A because matching is case-insensitive by default, and the empty cell on row 2 matched because blank cells count as missing.

Controls

Limits and edge cases

The table is capped at 5,000,000 bytes. A row shorter than the header stays short — missing trailing cells are not invented, because writing a value into a column the row never had would change its shape. Because the token list itself is comma-separated, a token that literally contains a comma cannot be expressed. Choosing never for output quoting can produce ambiguous CSV when a value contains the separator or a newline, so keep minimal unless a downstream reader demands otherwise. Output rows are terminated with a single newline (\n), and the result always ends with one. Everything runs locally in your browser — the table is never uploaded.

FAQ

Which tokens count as missing by default?

NA, N/A, N.A., #N/A, #N/A N/A, #NA, NULL, NIL, NaN, None, <NA>, -, --, and ? — plus any cell that is empty or whitespace-only. Matching ignores case and surrounding whitespace by default, so one NULL entry covers null, Null, and NULL. The list is an editable field, not a fixed rule: add your own sentinels or delete the ones that are real values in your data.

A real value in my data is a dash — how do I protect it?

Two ways. Delete - from the Tokens that count as missing list so a dash is never treated as missing anywhere, or leave the list alone and use Only these columns to restrict the rewrite to the columns where a dash really does mean "no data". The header row is protected either way, so a column named - or NA always survives.

How do I produce a file a Postgres COPY can load?

Set Replace missing cells with to \N and load with COPY table FROM 'file.csv' WITH (FORMAT csv, HEADER, NULL '\N'), and leave Output quoting on minimal — Postgres only honours the NULL sentinel when it is unquoted.

If you were hoping to keep an empty string distinct from a NULL, that distinction cannot survive this tool: a bare empty cell and a quoted "" both read as the same empty value on the way in, so there is nothing left to tell apart on the way out. Use a sentinel like \N for the missing cells instead, and anything that is still blank is your empty string.

Will this fill in the missing values for me?

No, and that is deliberate. This tool only makes the representation consistent; it never invents data. Substituting a mean, median, most-frequent value, or a nearest-neighbour estimate is imputation, which changes your dataset's statistics and belongs in a dedicated imputation step you can review separately.

Does it handle TSV, semicolon, and pipe files?

Yes. Choose tab, semicolon, or pipe by name, type any single character, or pick auto to detect the separator from the first line (it counts candidates outside quoted fields and prefers a comma on a tie). Whatever separator comes in is what goes back out, so the file shape is preserved.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool csv-null-standardizer "id,score,notes
1,42,ok
2,NA,
3,null,-
4,n/a,NaN"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/csv-null-standardizer/?input=id%2Cscore%2Cnotes%0A1%2C42%2Cok%0A2%2CNA%2C%0A3%2Cnull%2C-%0A4%2Cn%2Fa%2CNaN&delimiter=comma&na_tokens=NA%2CN%2FA%2CN.A.%2C%23N%2FA%2C%23N%2FA%20N%2FA%2C%23NA%2CNULL%2CNIL%2CNaN%2CNone%2C%3CNA%3E%2C-%2C--%2C%3F&replace_with=NULL&blank_is_missing=true&case_sensitive=true&trim=true&header=true&columns=score%2Cnotes&quote_style=minimal

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.