Skip to main content

Daffy — Validate pandas & Polars DataFrames with Python Decorators

PyPI conda-forge Python Docs CI codecov

Validate your pandas and Polars DataFrames at runtime with simple Python decorators. Daffy catches missing columns, wrong data types, and invalid values before they cause downstream errors in your data pipeline.

Also supports Modin and PyArrow DataFrames.

  • ✅ Column & dtype validation — lightweight, minimal overhead
  • ✅ Value constraints — nullability, uniqueness, range checks
  • ✅ Row validation with Pydantic — when you need deeper checks
  • ✅ Works with pandas, Polars, Modin, PyArrow — no lock-in

Installation

pip install daffy

or with conda:

conda install -c conda-forge daffy

Works with whatever DataFrame library you already have installed. Python 3.10–3.14.


Quickstart

from daffy import df_in, df_out

@df_in(["price", "bedrooms", "location"])
@df_out(["price_per_room", "price_category"])
def analyze_housing(houses_df):
    # Transform raw housing data into price analysis
    return analyzed_df

If a column is missing, has wrong dtype, or violates a constraint — Daffy fails fast with a clear error message at the function boundary.


Why Daffy?

Most DataFrame validation tools are schema-first (define schemas separately) or pipeline-wide (run suites over datasets). Daffy is decorator-first: validate inputs and outputs where transformations happen.

Non-intrusive Just add decorators — no refactoring, no custom DataFrame types, no schema files
Easy to adopt Add in 30 seconds, remove just as fast if needed
In-process No external stores, orchestrators, or infrastructure
Pay for what you use Column validation is essentially free; opt into row validation when needed

Examples

Column validation

from daffy import df_in, df_out

@df_in(["Brand", "Price"])
@df_out(["Brand", "Price", "Discount"])
def apply_discount(df):
    df = df.copy()
    df["Discount"] = df["Price"] * 0.1
    return df

Regex column matching

Match dynamic column names with regex patterns:

@df_in(["id", "r/feature_\\d+/"])
def process_features(df):
    return df

Value constraints

Vectorized checks with zero row iteration overhead:

@df_in({
    "price": {"checks": {"gt": 0, "lt": 10000}},
    "status": {"checks": {"isin": ["active", "pending", "closed"]}},
    "email": {"checks": {"str_regex": r"^[^@]+@[^@]+\.[^@]+$"}},
})
def process_orders(df):
    return df

Available checks: gt, ge, lt, le, between, eq, ne, isin, notnull, str_regex Also supported: notin, str_startswith, str_endswith, str_contains, str_length

Nullability and uniqueness

@df_in({
    "user_id": {"unique": True, "nullable": False},  # user_id must be unique and not null
    "email": {"nullable": False},  # email cannot be null
    "age": {"dtype": "int64"},
})
def clean_users(df):
    return df

Row validation with Pydantic

For complex, cross-field validation:

pip install 'daffy[pydantic]'
from pydantic import BaseModel, Field
from daffy import df_in

class Product(BaseModel):
    name: str
    price: float = Field(gt=0)
    stock: int = Field(ge=0)

@df_in(row_validator=Product)
def process_inventory(df):
    return df

Daffy vs Alternatives

Use Case Daffy Pandera Great Expectations
Function boundary guardrails ✅ Primary focus ⚠️ Possible ❌ Not designed for
Quick column/type checks ✅ Lightweight ⚠️ Requires schemas ⚠️ Requires setup
Complex statistical checks ⚠️ Limited ✅ Extensive ✅ Extensive
Pipeline/warehouse QA ❌ Not designed for ⚠️ Some support ✅ Primary focus
Multi-backend support ✅ ⚠️ Varies ✅

Configuration

Configure Daffy project-wide via pyproject.toml:

[tool.daffy]
strict = true

Documentation

Full documentation available at daffy.readthedocs.io


Contributing

Issues and pull requests welcome on GitHub.

License

MIT

Metadata

Release files for daffy 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for daffy 3.1.0
File Size Uploaded
daffy-3.1.0.tar.gz 70.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for daffy 3.1.0
File Interpreter ABI Platform
daffy-3.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 100.8 kB

Release files / daffy-3.1.0.tar.gz

Download URL daffy-3.1.0.tar.gz
Size 70.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d4e538eab526d821b45db26a5f95e765a982a765c2af565d7fc864577313798e
BLAKE2b-256 checksum
How to use checksums
7b6b03432499964506fbcc10ad1d62362938243276511cb8e4c04fefa7f7447c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release files / daffy-3.1.0-py3-none-any.whl

Download URL daffy-3.1.0-py3-none-any.whl
Size 30.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
afb4e5f925294c4ccdafe126f65a12b61ebcd614ec5d25f5210395836181d456
BLAKE2b-256 checksum
How to use checksums
ef930b01219044adfcd003d4b4003a4abcaaaee11b8e652c413a949d6422104b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.1.0 This release

2 release files

3.0.0

2 release files

2.8.0

2 release files

2.7.0

2 release files

2.6.1

2 release files

2.6.0

2 release files

2.5.1

2 release files

2.5.0

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.1

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

0.17.1

2 release files

0.17.0

2 release files

0.16.1

2 release files

0.16.0

2 release files

0.15.0

2 release files

0.14.2

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.2

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page