Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pandastrace-0.3.1.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pandastrace-0.3.1-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

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

Hashes for pandastrace-0.3.1.tar.gz
Algorithm Hash digest
SHA256 72cfab22cc52c518494aaf417cccefe33791f6a8a5fd42af38f778539c56c10a
MD5 84ef26ddf33fe7ba346e5f6fd3305e47
BLAKE2b-256 3f2ad85fe20db06421062c3cc0614d65cce31287eeb0560218f1434f61cb67c5

See more details on using hashes here.

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

Hashes for pandastrace-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 88bcb9256131e544a93344a174bde43b48072ef6b58f3c2b6281e54b2af9402d
MD5 8f1ab83dbe92e4e1be7c046046e1be02
BLAKE2b-256 c780344b69f0f4d62f97bc602852823988192722957b44e1ad5ef0bbc6e34a2a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page