Skip to main content

pytae

PyPI Python CI License

Fast, ergonomic Pandas tools and zero-code CLI for tabular data manipulation, feature engineering, DuckDB SQL, and visualization.

pytae provides two complementary ways to work with tabular data:

  1. Python Library & DataFrame Accessor (df.pt): Ergonomic data-science verbs (qry, select, mutate, agg, long, wide, pivot, sql, plot) that compose smoothly with vanilla Pandas.
  2. Unix Pipeline CLI (pytae): Inspect, filter, derive columns, aggregate, join, diff, and convert tabular files (.parquet, .csv, .tsv, .jsonl, .dat, .sas7bdat, .gz) directly from the terminal without writing Python code.

Quick Navigation


Installation

pip install pytae              # Core library and CLI
pip install "pytae[plot]"       # Includes matplotlib & scipy for plotting
pip install "pytae[sql]"        # Includes DuckDB for SQL queries
pip install "pytae[plot,sql]"   # All optional dependencies

Quick Start: CLI

pytae commands execute in exact terminal order like a Unix pipeline:

# 1. Fast inspection: view shape, schema, and first 5 rows without reading full files
pytae penguins.parquet -shape -head 5

# 2. Filter, engineer features, sort, and export to CSV
pytae penguins.parquet \
  -qry "species = 'Adelie', body_mass_g > 3500" \
  -mutate "mass_kg = body_mass_g / 1000, ratio = bill_length_mm / bill_depth_mm" \
  -sort_by "mass_kg desc" \
  -select "species,island,mass_kg,ratio" \
  -o heavy_adelie.csv

# 3. Grouped window calculation: calculate group mean and deviation per row
pytae tips.parquet \
  -by day \
  -mutate "avg_tip = mean(tip), diff = tip - avg_tip, sz = n" \
  -round 2 \
  -head 5

# 4. Grouped aggregation and pivoting
pytae penguins.parquet \
  -by 'island,species' \
  -agg 'avg_mass=body_mass_g:mean, count=n' \
  -wide 'c=species, v=avg_mass' \
  -round 1

# 5. Query any dataset using DuckDB SQL
pytae sales.parquet -sql "select customer_id, sum(total) as revenue from data group by 1 order by 2 desc" -head 10

# 6. Compare schemas and values between two files
pytae current.parquet -diff previous.parquet

# 7. In-line terminal visualizations & ASCII charts
pytae penguins.parquet -freq species
pytae penguins.parquet -hist body_mass_g:10

# 8. Render and export figures directly from the CLI
pytae penguins.parquet -by species -agg "body_mass_g=mean" -plot "kind=bar, x=species, y=body_mass_g" -o mass_chart.png

# 9. Pipe streaming via standard input (STDIN)
cat penguins.csv | pytae - -select "species,island" -value_counts

👉 Full CLI Guide: docs/cli.md | Individual Feature Guides: docs/cli/


Quick Start: Python Library

Use verbs as standalone functions (pt.verb(df, ...)) or chain them naturally on any DataFrame via the .pt accessor (df.pt.verb(...)):

import pytae as pt
import pandas as pd

# Load sample dataset
penguins = pt.sample("penguins")

# Clean, expressive pipeline
summary = (
    penguins
    # 1. Row filtering with comparison and intervals
    .pt.qry(species=["Adelie", "Gentoo"], body_mass_g=">= 3500")
    # 2. Grouped window calculation (N -> N)
    .pt.mutate(
        mass_kg="body_mass_g / 1000",
        avg_mass="mean(body_mass_g)",
        diff="body_mass_g - avg_mass",
        by="species",
    )
    # 3. Select columns with negative drop support
    .pt.select("species", "island", "mass_kg", "diff")
    # 4. Grouped aggregation (N -> K)
    .pt.agg(by="species", mean_mass="mass_kg.mean()", count="n")
)

print(summary)

👉 Full Library Guide: docs/library.md | Interactive Tutorials: docs/library/


Key Features

1. Row Filtering (qry)

Filter rows without boilerplate. Accepts Python keywords, string expressions, and mathematical intervals:

# Keywords, lists, and closed intervals [3000, 4000]
df.pt.qry(species=["Adelie", "Gentoo"], body_mass_g="[3500, 4500]")

# Columns containing spaces use square brackets
df.pt.qry("[bill length mm] > 40")

# Missing value checks
df.pt.qry(sex=("notna",))

2. Column Creation & Grouped Window Calculations (mutate)

Derive columns with Python/Pandas expressions, dplyr-style conditionals (if_else, case_when, coalesce), and grouped window summaries:

# Formulas, vectorized conditionals, and caller-scope variables (@threshold)
threshold = 4000
df.pt.mutate(
    mass_kg="body_mass_g / 1000",
    size_class="if_else(body_mass_g > @threshold, 'Large', 'Normal')",
)

# Grouped window calculations: aggregates evaluate per group and broadcast back (N -> N)
df.pt.mutate(
    avg_mass="mean(body_mass_g)",
    diff="body_mass_g - avg_mass",
    group_size="n",
    by="species",
)

3. Column Selection & Exclusion (select)

Reorder, slice, and filter columns using names, patterns, types, and negative drops:

# Negative selection (drop specific columns)
df.pt.select("-id", "-temp")

# By pattern, dtype, and position
df.pt.select("species", contains="bill", dtypes="numeric")

# Reorder with everything helper
df.pt.select("island", "species", pt.everything)

4. Grouped Aggregation (agg)

Concise group summaries with explicit by= grouping, bracket support for spaced names, and automatic row count token n:

# Explicit grouping and named aggregations
df.pt.agg(by="species", avg_mass="body_mass_g.mean()", n="n")

# String mapping specification (perfect for spaced columns)
df.pt.agg("island", "[avg mass] = [body mass g]:mean, n = n")

5. Pure Reshaping (long & wide)

Clean, deterministic unpivoting (melting) and spreading without MultiIndex complexity:

# 1. Unpivot non-numeric columns into key-value pairs
long_df = df.pt.long(id_vars=["species", "island"], cols=["bill_length_mm", "bill_depth_mm"])

# 2. Pure reshape back to wide presentation matrix
wide_df = long_df.pt.wide(c="variable", v="value")

6. 2D Pivot Tables (pivot)

Excel-style 2D pivot tables with automatic index reset and flat 1D columns:

# 2D grid summarizing average body mass across island and species
pivot_df = df.pt.pivot(r="island", c="species", v="body_mass_g", a="mean")

# Frequency matrix (count rows across dimensions; v is optional for a="n")
freq_matrix = df.pt.pivot(r="island", c="species", a="n")

7. Embedded DuckDB SQL Engine (sql)

Run analytical SQL directly on any Pandas DataFrame with zero copy:

result = df.pt.sql("""
    select species, count(*) as total, round(avg(body_mass_g), 1) as avg_mass
    from data
    where body_mass_g is not null
    group by 1
    order by avg_mass desc
""")

8. Visualization (plot)

Method-chainable charting powered by Matplotlib (pip install "pytae[plot]"):

# Direct accessor chaining:
penguins.pt.plot(
    kind="scatter",
    x="bill_length_mm",
    y="bill_depth_mm",
    c="species",
    cmap="viridis",
    title="Penguin Bill Dimensions",
).pt.finalize()

# One-shot direct file export (no explicit finalize required):
penguins.pt.agg("species", body_mass_g="mean").pt.plot(kind="bar", x="species", y="body_mass_g").save("mass.png")

9. Zero-Cost Metadata Inspection & Diffing

Inspect large Parquet, CSV, and SAS datasets instantly without loading millions of rows into memory:

# Instant shape, columns, and types from Parquet file headers
pytae large_dataset.parquet -shape -cols -meta

# Compare schemas, null counts, and value differences across datasets
pytae current.parquet -diff previous.parquet

Key Syntax & Conventions Cheat Sheet

Task Python Library (df.pt) CLI Flag Example
Row Filtering .pt.qry(...) -qry "..." df.pt.qry(species="Adelie", mass="> 3500")
Spaced Columns (Expr) [column name] [column name] df.pt.mutate(ratio="[bill length mm] / [bill depth mm]")
Grouped Window Calc .pt.mutate(..., by=...) -by ... -mutate "..." pytae data.parquet -by dept -mutate "avg=mean(salary)"
Negative Column Select .pt.select("-col1", "-col2") -select "-col1,-col2" df.pt.select("-temp", "-raw_id")
2D Pivot Table .pt.pivot(...) -pivot "..." df.pt.pivot(r="Region", c="Year", v="Sales", a="sum")
Data Reshaping .pt.long(), .pt.wide() -long, -wide df.pt.wide(c="metric", v="val")
In-Line Terminal Charts N/A -freq, -hist pytae data.parquet -freq species / -hist mass:10
Figure Plotting & Export .pt.plot(..., save=...) -plot "..." -o ... pytae data.parquet -plot "kind=bar, x=sp, y=wt" -o out.png
DuckDB SQL Query .pt.sql("select ...") -sql "select ..." pytae data.parquet -sql "select * from data limit 5"
Pipe / STDIN Stream N/A pytae - [-fmt ...] cat data.csv | pytae - -head 5
Copy to Clipboard df.to_clip() -o clip df.head().to_clip() vs pytae data.parquet -head -o clip
File Export & Routing df.to_parquet(...) -o <target.ext> pytae data.parquet -o clean.csv.gz -od ./exports
Dataset Diffing N/A -diff <other_file> pytae data.parquet -diff old_data.parquet

Documentation & Interactive Tutorials

CLI Documentation (docs/cli/)

Interactive Jupyter Notebooks (docs/library/)

Each core module has a standalone, fully runnable tutorial with live outputs:


License

MIT License. See LICENSE for details.

Metadata

Release files for pytae 3.7.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 pytae 3.7.0
File Size Uploaded Provenance
pytae-3.7.0.tar.gz 3.0 MB Without provenance Details

Built distribution (wheel)

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

Total release size: 4.8 MB

Release files / pytae-3.7.0.tar.gz

Download URL pytae-3.7.0.tar.gz
Size 3.0 MB
Tags Source
SHA-256 checksum
How to use checksums
6ba321e95778f9779b540687ae321a758f92e00b8e41d2ad8c243ae2a06a9c55
BLAKE2b-256 checksum
How to use checksums
2dd4895c3adf10e91d16ffbbabab912beb405748cb195037e0b0eb58aed19d7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / pytae-3.7.0-py3-none-any.whl

Download URL pytae-3.7.0-py3-none-any.whl
Size 1.8 MB
Tags Python 3
SHA-256 checksum
How to use checksums
e2e013be24fd96ccb3b63ab3e4e4b690b8936d5d117ea995646d1a6a175399a7
BLAKE2b-256 checksum
How to use checksums
82e6faf7ef657efd667fd8e10332601ccd7f1a185f47f32923d357f74fe0a449
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for pytae 3.7.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

3.7.0 This release

2 release files No provenance

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