csv-data-profiler
Skill2 starsChanged 4 months agoMITView on GitHub
Profiles tabular datasets (CSV, TSV, Excel, Parquet, JSONL) to produce a structured quality report covering schema inference, missingness, cardinality, distributions, outliers, duplicates, format inconsistencies and suggested cleaning steps. Use when the user shares a data file, asks what is in a dataset, asks about data quality, wants an exploratory first look, or needs to decide whether data is fit for analysis or modelling.
In this repository13 other files it gives its agents.
- AGENTS.mdAGENTS.md
- accessibility-auditorSkill
- contract-reviewerSkill
- dependency-auditorSkill
- git-workflow-assistantSkill
- meeting-notes-to-actionsSkill
- prompt-engineering-optimizerSkill
- release-notes-generatorSkill
- rest-api-designerSkill
- security-code-reviewSkill
- sql-query-optimizerSkill
- technical-writing-editorSkill
- web-research-synthesizerSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 25
Do not use for: answering a specific analytical question (profile first, then analyse), or streaming/real-time data.
- Distinctive: line 32
Ask what the data is for — reporting, joining, training a model, migration.
- Distinctive: line 48
Only inspect the raw file directly when the script fails (malformed quoting, non-UTF-8 encoding, ragged rows) — then diagnose and re-run.
- Distinctive: line 53
If the user has a schema, a previous delivery or stated expectations, check the file against them rather than only describing it:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CSV Data Profiler
Answer three questions about any dataset: what is in it, what is wrong with it, and can I trust it for the intended use?
When to use
First contact with an unfamiliar dataset; a pipeline started producing odd results; validating a vendor delivery; pre-modelling sanity checks.
Do not use for: answering a specific analytical question (profile first, then analyse), or streaming/real-time data.
Workflow
0. Establish intent before profiling
Ask what the data is for — reporting, joining, training a model, migration. The intended use decides which defects are fatal versus cosmetic. If the user does not answer, profile generically and say so.
1. Run the profiler script, do not eyeball the file
Deterministic computation beats token-generated statistics.
python3 scripts/profile.py data.csv --output report.md --sample 200000The script handles delimiter sniffing, encoding detection, mixed types and large
files via sampling. Read references/interpretation.md for how to read edge
cases in its output.
Only inspect the raw file directly when the script fails (malformed quoting, non-UTF-8 encoding, ragged rows) — then diagnose and re-run.
1b. Validate against expectations when a contract exists
If the user has a schema, a previous delivery or stated expectations, check the file against them rather than only describing it:
python3 scripts/validate_schema.py data.csv --schema expectations.json --format mdThe schema file declares per-column type, nullability, ranges, allowed values,
regex patterns and uniqueness. Generate a starting point from a known-good file
with --infer, then edit the thresholds. This turns profiling into a repeatable
gate you can run on every delivery.
2. Structural checks
| Check | Red flag |
| Row / column count | 0 rows; a column count that differs from the header |
| Header quality | Duplicated names, unnamed columns, spaces or units in names |
| Ragged rows | Any row whose field count ≠ header count |
| Encoding | Mojibake (é, ’) means a UTF-8/Latin-1 mix-up |
| Delimiter | Fields containing the delimiter without quoting |
| Trailing junk | Totals row, blank rows, footnote lines at the bottom |
3. Per-column profile
For every column report: inferred type, null count and %, distinct count, % unique, top 5 values with frequencies, and an example value.
Additionally:
- Numeric: min, p1, q1, median, mean, q3, p99, max, std, zero count, negative count, outliers by IQR (< q1 − 1.5·IQR or > q3 + 1.5·IQR).
- Categorical: full value set if ≤ 30 distinct, else top 20 + long-tail size; case/whitespace variants of the same value.
- Datetime: min, max, parse-failure count, future dates, epoch-zero
sentinels (
1970-01-01), mixed formats, timezone presence. - Text: min/max/mean length, empty-string count, detected patterns (email, URL, UUID, phone, postcode), pattern-violation count.
- Boolean-ish: which encodings appear (
true/false/1/0/Y/N/yes/no).
4. Quality issue catalogue
| Issue | Detection | Severity |
| High missingness | > 30 % null | High if the column is a key or target |
| Constant column | 1 distinct value | Medium — no information |
| Near-duplicate rows | Identical on all but 1–2 columns | High for keys |
| Exact duplicate rows | Full-row hash collision | High |
| Broken candidate key | % unique between 95 % and 100 % | High |
| Mixed types in a column | Numbers and text coexist | High |
| Placeholder nulls | "NA", "N/A", "-", "null", "", -1, 9999, -999 | High — silent corruption |
| Whitespace / case variants | "Paris " vs "paris" | Medium |
| Number-as-text | Numeric column stored as string, or thousands separators | Medium |
| Locale decimal mix | 1,5 and 1.5 in one column | High |
| Impossible values | Negative age, > 100 % rate, future birth date | High |
| Referential gaps | FK values absent from the dimension table | High |
| Class imbalance | Target minority class < 5 % | Medium for modelling |
| Leakage suspects | A feature correlating ≥ 0.98 with the target | High for modelling |
| Truncation | Many values at exactly 255 / 50 chars | Medium |
| Timezone ambiguity | Naive timestamps spanning a DST boundary | Medium |
5. Cross-column checks
Pairwise correlation on numerics (flag |r| > 0.95); functional dependencies
(A determines B → possible denormalisation); logical rules (end_date >= start_date,
quantity * unit_price ≈ total); grain verification (which column combination is unique?).
6. Report
# Data Profile: <filename>
## Verdict
Fit for <intended use>: YES / WITH FIXES / NO — one-sentence reason.
## Overview
Rows, columns, size, encoding, delimiter, inferred grain, memory footprint.
## Critical issues (blocks the intended use)
## Warnings (needs a decision)
## Column reference (the full table)
## Recommended cleaning (ordered, with runnable code)
## Open questions for the data ownerLead with the verdict. State counts and percentages, never "some rows".
Tools
| Script | Use |
scripts/profile.py | Full quality profile: types, missingness, distributions, duplicates, correlations |
scripts/validate_schema.py | Assert a file against an explicit contract; --infer bootstraps the contract |
python3 scripts/profile.py data.csv --output report.md --sample 200000
python3 scripts/validate_schema.py clean.csv --infer > expectations.json
python3 scripts/validate_schema.py new_delivery.csv --schema expectations.jsonBoth exit non-zero on failure, so they drop straight into a pipeline.
Worked example
transactions.csv — 1 284 302 rows × 14 columns.
Critical
customer_id— 99.7 % unique but not a key: 3 812 rows share IDs across differentemailvalues. Grain is actually(customer_id, order_date).amount— stored as text; 41 209 values use a comma decimal separator ("1,50"). Naivefloat()casting drops them to null and understates revenue by ~3.2 %.signup_date— 8 104 rows equal1970-01-01(epoch sentinel, not real dates).
Warnings
country— 214 distinct values for ~50 real countries: case and whitespace variants ("FR","fr","France ","FRA").discount_pct— max 340; 92 rows exceed 100.
Cleaning order: fix encoding → normalise placeholder nulls → cast types (locale-aware) → deduplicate → standardise categories → validate rules → re-profile.
Quality checklist
- Every column appears in the report, none skipped
- Where a contract exists,
validate_schema.pywas run and its failures reported - All figures come from the script, not from estimation
- Percentages accompany every raw count
- Issues ranked by impact on the stated intended use
- Cleaning steps are runnable and ordered by dependency
- Sampling disclosed if the file was sampled
- No PII values reproduced in the report — mask or describe them
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

