The head of your CSV is lying: how 9,291 invoice numbers almost vanished

Real transaction data is never clean — and the worst part is that it looks clean. This is a short story from a real dataset (UCI Online Retail: 541,909 e-commerce transactions) about the quietest way to destroy data: silent type coercion. All numbers b…


This content originally appeared on DEV Community and was authored by Ahmed Abdeltawab

Real transaction data is never clean — and the worst part is that it looks clean. This is a short story from a real dataset (UCI Online Retail: 541,909 e-commerce transactions) about the quietest way to destroy data: silent type coercion. All numbers below come verbatim from an executed notebook.

The head looks perfect

Peek at the first rows of the file and InvoiceNo parses as clean integers — 100% parse rate, full confidence. Any type-inference step, mine included, would call it int64 and move on.

Measure the whole file instead of the head, and the number drops to ~98%. The other 2%: invoice numbers starting with "C" — which in this dataset marks a cancellation. Coerce the column to numeric and every one of them becomes NaN:

Invoice numbers destroyed by numeric coercion: 9,291

DextraLoaderWarning: load: ambiguous decision(s):
column 'InvoiceNo': ambiguous - float64 at parse_rate=0.98

An entire class of business events — silently gone. No exception, no crash. That's what makes coercion the quietest bug in data work: the pipeline succeeds.

Why those 9,291 rows matter

They are not noise. They are the returns side of the business: cancelled orders worth 8.4% of everything sold. Lose them and every revenue number downstream is quietly wrong.

One example of what they catch: the dataset's apparent #1 bestseller, "PAPER CRAFT, LITTLE BIRDIE" (168,470 GBP), is a phantom — a single 80,995-unit order entered at 09:15 and fully cancelled at 09:27 the same morning. Only the preserved cancellation rows expose it. The genuine bestseller is a cake stand.

The fix: identifiers are labels, not quantities

No library can know that "InvoiceNo" is an ID — that's domain knowledge. What a tool can do is disclose its guess and hand you a replayable plan you can correct:

naive, plan = dx.load(CSV_PATH, return_params=True)   # warns: ambiguous at 0.98

plan["columns"]["InvoiceNo"]["dtype"] = "object"      # invoices are labels
plan["columns"]["StockCode"]["dtype"] = "object"      # product codes too

df = dx.load(CSV_PATH, params=plan)                   # deterministic replay
Cancellation invoices preserved: 9,288
InvoiceNo values lost: 0

The correction is now documented, versionable code — not a mystery cell someone ran once.

Three habits this taught me

  1. Never trust the head of a file. The first rows parse clean at 100%; the truth lives in the full-file parse rate. Measure every cell.
  2. Declare identifiers explicitly. Invoice numbers, product codes, phone numbers, zip codes — they look numeric and they are not. One schema line prevents the whole class of bug.
  3. Split, don't delete. The final frame here is three frames: sales (530,104 rows, 97.8%), returns (9,288, 1.7%), oddities (2,517, 0.5%). Deleted rows can't answer questions later; split rows can — the returns table is where the phantom bestseller was caught.

Try it

The full walkthrough — from messy CSV to a business decision, every step printing what it did and why — is published fully executed on Kaggle: Rescuing 9,291 invoices from coercion (pydextra).

It runs on pydextra (pip install pydextra, MIT), a small library I built around one idea: every function prints a one-line Decision: explaining what it did and why. To be transparent: it's a personal educational-practical project, not a replacement for pandas — pandas is the engine underneath.

Data: Chen, D. (2015). Online Retail. UCI Machine Learning Repository. DOI 10.24432/C5BW33, CC BY 4.0.


This content originally appeared on DEV Community and was authored by Ahmed Abdeltawab


Print Share Comment Cite Upload Translate Updates
APA

Ahmed Abdeltawab | Sciencx (2026-08-15T06:19:41+00:00) The head of your CSV is lying: how 9,291 invoice numbers almost vanished. Retrieved from https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/

MLA
" » The head of your CSV is lying: how 9,291 invoice numbers almost vanished." Ahmed Abdeltawab | Sciencx - Saturday August 15, 2026, https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/
HARVARD
Ahmed Abdeltawab | Sciencx Saturday August 15, 2026 » The head of your CSV is lying: how 9,291 invoice numbers almost vanished., viewed ,<https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/>
VANCOUVER
Ahmed Abdeltawab | Sciencx - » The head of your CSV is lying: how 9,291 invoice numbers almost vanished. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/
CHICAGO
" » The head of your CSV is lying: how 9,291 invoice numbers almost vanished." Ahmed Abdeltawab | Sciencx - Accessed . https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/
IEEE
" » The head of your CSV is lying: how 9,291 invoice numbers almost vanished." Ahmed Abdeltawab | Sciencx [Online]. Available: https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/. [Accessed: ]
rf:citation
» The head of your CSV is lying: how 9,291 invoice numbers almost vanished | Ahmed Abdeltawab | Sciencx | https://www.scien.cx/2026/08/15/the-head-of-your-csv-is-lying-how-9291-invoice-numbers-almost-vanished/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.