Home/Blog/How to Prompt a Pandas ETL Contract from a CSV
Blog

How to Prompt a Pandas ETL Contract from a CSV

P
promptstudio
How to Prompt a Pandas ETL Contract from a CSV

Messy CSVs tempt models to be janitors and inventors at once. They mint columns nobody asked for, guess dtypes from three pretty rows, fill nulls with zeros, and emit a pipeline that handles millions of rows when you pasted forty. The contract you wanted was: here is the sample, here are the types, here is what we do with nulls, here is what we refuse to invent.

The matching generator is the Pandas ETL Contract from a Messy CSV prompt. Browse related cards in the PromptDig library (Browse more prompts). When a filled run survives, share the version you actually use (Share a prompt).

The sample is the schema; unread files are UNVERIFIED

Paste a header plus enough rows to show the mess: mixed dates, blank cells, yes/no/TRUE, commas in numbers, a stray extra delimiter. Infer dtypes from that sample only. If a column looks integer except for "n/a", the contract is nullable integer or object, not int64 with silent coercion.

Never mint columns. A derived is_late flag is a new column. If Inputs did not ask for it, it goes under Gaps or a clearly labeled optional transform, not into the default frame.

If the user described a file they did not paste, treat row counts, encodings, and delimiter guesses as UNVERIFIED. Do not claim UTF-8 just because it is common. If encoding is unnamed, write unknown.

Version-lock Pandas when Inputs name it (the card is written for 2.2-era contracts). If they did not name a version, write unknown. Do not float on a tutorial's 1.x NA behavior as if it were current.

Null policy, date parsing, and failure modes

Null policy is explicit: which sentinels count as missing ("", NA, n/a, None), which stay as data, whether to use pandas NA. Filling with zero is a business decision. If Inputs did not authorize it, refuse.

Dates: format strings you can see in the sample. If US and EU numeric dates are both possible, do not pick one. List the collision under Edge cases.

Dtypes: nullable integer where needed, string dtype instead of object when you mean text, categoricals only if the sample shows a small closed set. Do not invent a category for a free-text notes column.

Failure modes: extra columns in a later file, missing required columns, duplicate keys, timezone-naive stamps, scientific notation IDs that rounded in Excel. Each needs a check that fails loud, not a coerce-and-continue.

If the CSV is clinical, HR, insurance, or education-plan adjacent, de-identify first and add a one-line not-advice banner. Do not leave emails, phones, or MRNs in the sample you paste into a prompt.

Tests, acceptance, and a gaps list

Validation checklist: read_csv with the stated dtype map, assert columns equal the header set, assert no extra columns, assert null sentinels match policy, parse one known date, reject a row that is missing a required key. Do not claim a pass on data you were not given.

Acceptance checks from Inputs only. If they wanted "load without inventing SKU," the test is column set equality, not a fictional completeness percent.

Gaps: full file row count, delimiter if the paste is ambiguous, timezone, primary key, allowed value lists, destination table, Pandas version if unnamed. Five bullets the user still owes you is a successful output. A 200-line pipeline with a minted customer_lifetime_value is not.

Stay on the contract. Plotting, a Streamlit app, and a Snowflake loader are out of scope unless the spec named them.

Fill the card, then run

Paste a real header and messy rows. Name Pandas if you pin it. Say what must never be filled.

Goal: [ETL contract, not a dashboard]
CSV sample (header + messy rows): [Paste]
Stack versions: [Pandas x.y or unknown]
Constraints: [Required columns, sentinels, timezone]
Forbidden: [Minted columns, fillna zeros, invented row counts]
Acceptance checks: [Column set, dtype map, fail-loud rules]

The useful artifact is a dtype map, a null policy, and a refuse list. When a run marks a derived column FORBIDDEN and leaves encoding unknown, share that filled card. The next messy export will look the same, only worse.