Debug pandas method chains step-by-step — row, null, duplicate, and memory tracking at every step.
Project description
PandasTrace
Debug pandas method chains, step by step.
Ever run a chain like this and get a result that's just... wrong?
df = (df.dropna()
.merge(other_df, on="user_id")
.groupby("country")
.agg({"sales": "sum"}))
You have no idea which step broke it — did dropna() wipe out more rows than expected? Did the merge() silently duplicate rows? PandasTrace watches your chain and shows you exactly what happened at every step, without you writing a single debug print().
The problem
Normally, debugging a chain like the one above means manually breaking it into separate lines, adding print(df.shape) after each one, re-running, then deleting all that debug code once you've found the issue. Every data analyst and ML engineer has done this — it's tedious and easy to skip, which means bugs slip through.
What PandasTrace does
Wrap your DataFrame once, keep chaining exactly like you normally would, and get a clean report of what happened at every step:
from pandastrace import TraceFrame, TraceReporter
result = (
TraceFrame(df)
.dropna()
.merge(other_df, on="user_id")
.groupby("country").agg({"sales": "sum"})
)
TraceReporter(result.recorder()).print_table()
PandasTrace Report
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Method ┃ Shape Before ┃ Shape After ┃ Row Delta┃ Null Changes ┃ Duplicates ┃ Memory ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━┩
│ dropna │ (8, 3) │ (6, 3) │ -2 │ country: -2 │ - │ -132.0B │
│ merge │ (6, 3) │ (7, 4) │ +1 │ - │ +1 │ +210.0B │
│ groupby().agg │ (7, 4) │ (3, 1) │ -4 │ sales: -3 │ - │ -360.0B │
└───────────────┴──────────────┴─────────────┴──────────┴──────────────┴────────────┴──────────┘
Row losses show in red, gains in green, new duplicates in red, memory growth in yellow. Notice the merge step here shows Duplicates: +1 — this is PandasTrace catching a real bug: the merge key had a duplicate row on the right side, silently multiplying a row in the result. Also notice groupby().agg shows up as one combined step, spanning all the way back to before .groupby() was called — PandasTrace correctly waits until pandas returns something with a real shape before logging, so nothing gets silently lost mid-chain.
Installation
pip install pandastrace
Quick start
import pandas as pd
from pandastrace import TraceFrame, TraceReporter
df = pd.DataFrame({
"user_id": [1, 2, 3, 4, 5, 6],
"country": ["PK", "US", None, "PK", "UK", None],
"sales": [100, 200, 150, None, 300, 250],
})
traced = TraceFrame(df).dropna().head(3)
TraceReporter(traced.recorder()).print_table()
Need the raw DataFrame back once you're done tracing? Call .unwrap():
clean_df = traced.unwrap()
Want the data as plain Python objects instead of a printed table (e.g. to log it, export it, or feed it elsewhere)?
TraceReporter(traced.recorder()).to_dict_list()
# [{"method": "dropna", "before": (6, 3), "after": (3, 3), "delta": -3}, ...]
How it works
TraceFrame wraps your DataFrame and intercepts every method call you make on it. Before running the real pandas operation, it records the shape; after running it, it records the shape again — then logs the difference. The result is wrapped back into a new TraceFrame, so chaining keeps working exactly like normal pandas.
Current features (v0.3)
- Row count tracking across any chained pandas method
- Null count tracking per column, per step — see exactly which column gained or lost missing values at each stage
- Duplicate row detection — catch bad merges that silently multiply rows before they cause downstream bugs
- Memory usage tracking per step, human-readable (KB/MB/GB)
- Export full trace history to JSON or CSV — useful for logging results from automated/CI pipelines, not just interactive debugging
- Correctly handles multi-call operations like
.groupby().agg()as a single combined step, instead of losing track mid-chain - Works with
[...]column indexing as well as method chaining - Colored terminal output (red = rows/data lost or new duplicates, green = shrinking/cleanup, yellow = memory growth)
- Zero changes needed to your existing pandas code — just wrap the DataFrame
Roadmap
- VS Code extension — see diagnostics inline in your editor as you write the chain
Contributing
Issues and PRs welcome. This is an early-stage project — if you hit a pandas method that doesn't behave correctly under tracing, please open an issue with a minimal reproduction.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pandastrace-0.3.1.tar.gz.
File metadata
- Download URL: pandastrace-0.3.1.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72cfab22cc52c518494aaf417cccefe33791f6a8a5fd42af38f778539c56c10a
|
|
| MD5 |
84ef26ddf33fe7ba346e5f6fd3305e47
|
|
| BLAKE2b-256 |
3f2ad85fe20db06421062c3cc0614d65cce31287eeb0560218f1434f61cb67c5
|
File details
Details for the file pandastrace-0.3.1-py3-none-any.whl.
File metadata
- Download URL: pandastrace-0.3.1-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88bcb9256131e544a93344a174bde43b48072ef6b58f3c2b6281e54b2af9402d
|
|
| MD5 |
8f1ab83dbe92e4e1be7c046046e1be02
|
|
| BLAKE2b-256 |
c780344b69f0f4d62f97bc602852823988192722957b44e1ad5ef0bbc6e34a2a
|