Skip to main content

pqfilt

Generic Parquet filtering tool (CLI and Python API).

ReadtheDocs Documentation.

Main Purpose

pqfilt wraps pyarrow.dataset to let you filter Parquet files before they are fully read into memory, using row-group-level filtering. This is very efficient/fast.

An image generated by GPT 5.6: Image

Moreover, pqfilt provides a simple CLI tool that the user can simply filter a large (GB-TB order) Parquet to a smaller CSV file for interactive use (see below).

  • Using pqfilt.read() with filters is faster than pd.read_parquet() on the measured SPHEREx datasets.
    • ~50× faster on the SPHEREx SSO ephemeris database (110 files, 139M rows; a 10-day jd_tdb window selects 4 files, 56 ms vs 2.957 s);
    • ~2× faster on a 3.6M-row SPHEREx source catalog (single row group, compound filter, all/four columns). Gains are larger when files have many row groups or the filter excludes whole files.
  • The syntax is designed to be intuitive and flexible
    • e.g., "a > 5 & ~(b in 1,2) & v is not null" is much simpler than the equivalent pyarrow expression syntax or chaining multiple DataFrame filters together.
  • Even if you already loaded a DataFrame, you can use pqfilt.filter_df(df, 'a > 5 & ~(b in 1,2) & v is not null') to apply the same filter syntax to it.

Installation

pip install pqfilt
# or
uv add pqfilt

Python API

import pqfilt

# Simple filter
df = pqfilt.read("data.parquet", filters="vmag < 20")

# AND + OR with expression syntax
df = pqfilt.read("data.parquet", filters="(a < 30 & b > 50) | c == 1")

# Negation with ~ prefix
df = pqfilt.read("data.parquet", filters="~(a > 5)")
df = pqfilt.read("data.parquet", filters="a > 5 & ~(b in 1,2,'1','2')")

# Null checks
df = pqfilt.read("data.parquet", filters="v is null")
df = pqfilt.read("data.parquet", filters="v is not null")

# Boolean columns
df = pqfilt.read("data.parquet", filters="is_comet == True")
df = pqfilt.read("data.parquet", filters="is_comet != false")

# Membership filter (explicit quotes preserve string types, e.g., to prevent Parquet type errors)
# Supported array formats: "val1, val2", "(val1, val2)", "[val1, val2]"
df = pqfilt.read("data.parquet", filters="desig in '1', '2', '3'")
df = pqfilt.read("data.parquet", filters="desig in ('1', '2', '3')")
df = pqfilt.read("data.parquet", filters="desig in ['1', '2', '3']")

# Tuple syntax (flat AND)
df = pqfilt.read("data.parquet", filters=[("a", "<", 30), ("b", ">", 50)])

# Tuple syntax with null checks
df = pqfilt.read("data.parquet", filters=[("v", "is null", None)])

# DNF syntax (OR of ANDs)
df = pqfilt.read("data.parquet", filters=[
    [("a", "<", 30)],
    [("b", ">", 50)],
])

# Column selection + output
df = pqfilt.read("data/*.parquet", columns=["a", "b"], output="out.parquet")

# Arrow scanner: materialize a table or consume record batches yourself
scanner = pqfilt.scan("data/*.parquet", filters="vmag < 20")
table = scanner.to_table()

# Out-of-core write: stream filtered batches directly to an output file
rows_written = pqfilt.write_filtered(
    "data/*.parquet",
    "filtered.parquet",
    filters="vmag < 20",
)

# Filter an already-loaded DataFrame (same syntax)
df = pd.read_csv("data.csv")
filtered = pqfilt.filter_df(df, "a > 5 & ~(b in 1,2) & v is not null")

CLI

# Basic filter
pqfilt data/*.parquet -f "vmag < 20" -o filtered.parquet

# AND + OR expression
pqfilt data/*.parquet -f "(a < 30 & b > 50) | c == 1" -o filtered.parquet

# Multiple -f flags (AND-ed together)
pqfilt data/*.parquet -f "vmag < 20" -f "dec > 30" -o filtered.parquet

# Column selection
pqfilt data/*.parquet -f "vmag < 20" --columns vmag,ra,dec -o filtered.parquet

# Membership filter (enclosing brackets [] or () are automatically stripped)
pqfilt data/*.parquet -f "desig in [1, 2, 3]" -o filtered.parquet

Column names with special characters

Columns containing operator characters can be backtick-quoted. Say you have a column named "alpha*360". Wrap it with backticks to avoid misinterpretation as a multiplication operator:

pqfilt.read("data.parquet", filters="`alpha*360` > 100")

Word operators (in, not in, is null, and is not null) must be preceded by whitespace. This grammar rule keeps an unquoted column name ending in in (such as spin or margin) from being misread as an operator. Symbolic operators do not have this requirement:

pqfilt.read("data.parquet", filters="spin > 3")
pqfilt.read("data.parquet", filters="margin in 1,2")

License

MIT

Release files for pqfilt 0.3.1

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

Source distribution (sdist)

Source distribution for pqfilt 0.3.1
File Size Uploaded
pqfilt-0.3.1.tar.gz 107.2 kB Details

Built distribution (wheel)

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

Total release size:125.2 kB

Release files / pqfilt-0.3.1.tar.gz

Download URL pqfilt-0.3.1.tar.gz
Size 107.2 kB
Tags Source
SHA-256 checksum
How to use checksums
828a6a9a7b58bb189e28d10a5e70215e7399a48efed259a186d982b6085d8d2b
BLAKE2b-256 checksum
How to use checksums
d3ab90fd5c5a04c12547b26da9b90c93fb880f80972254a701c536d1a3958033
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 Sep 7, 2026.

Transparency log

Release files / pqfilt-0.3.1-py3-none-any.whl

Download URL pqfilt-0.3.1-py3-none-any.whl
Size 18.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fbf7a43a38af586102c620762bcb6dbcfede92bae4dafc3247758fa720f7bd03
BLAKE2b-256 checksum
How to use checksums
e289cb8ca5a5d1032c7a22c82e4be777ffea1b4ee00f642e8f59a0f7c162a1ec
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 Sep 7, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.0

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

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