Group data locally with Query.group_by()
Build a columnar query with algenta.Query and group your own data locally with group_by() — the same composed engine the dataframe group-by benchmark measures.
By the end of this guide you will have built a query plan with algenta.Query, aggregated a column with group_by(), run it in one dispatch on your own machine, and read back the grouped result. Everything runs inside the runtime that ships with the algenta package — there is nothing separate to start, connect to, or manage.
Query(...).group_by(...) is the same public entry point Dataframe group-by measures: the "aggregate" operator resolves to the composed dense/packed/fused-radix engine that page benchmarks against DuckDB and Polars, not a separate, slower path.
Requirements
Python 3.12 or newer on a supported platform — macOS 13 or newer on Apple silicon, or Linux x86-64 or arm64 with glibc 2.34 or newer.
pip install algentainstalls the native runtimeQueryexecutes on; on any other platform the install fails. See Local native runtime for the full table.Data as columns of numbers. Cells are floats or
None; booleans are accepted and coerced to1.0/0.0. Non-numeric data (strings, dates) needs to be encoded to a numeric column before it reachesQuery— the same convention Dataframe group-by uses for its own categorical columns.
Install Algenta
python3 -m venv .venv
source .venv/bin/activate
pip install algentaRun a group-by
Build the query
Query takes a columns header and either rows (inline data) or a dataset handle (see Reusing one table across several queries). group_by(by, value, agg=...) appends one aggregate operator; by is a single column name or a list of them for a multi-key group.
from algenta import Query, col
query = (
Query(
columns=["region", "amount"],
rows=[[1, 10.5], [2, 50.0], [1, 30.0], [2, 5.0]],
)
.filter(col("amount") > 0)
.group_by("region", "amount", agg="sum")
.sort("sum_amount", desc=True)
)Chaining filter, sort, top_k, project, join and group_by costs nothing extra in round trips — the whole plan crosses into the runtime once, not once per operator.
Run it
from algenta import MojoRuntime
runtime = MojoRuntime(mode="local")
result = query.run(runtime, routing_module="stats")routing_module names the installed shard to dispatch through. "stats" is a safe default for a query that names no kernel directly — pick a shard you know is installed if you have filtered the runtime down (see Route & execute capabilities).
Group-by semantics
Accepted
aggtokens:sum,avg(aliasmean),min,max,count,var,std. Any other value raisesValueErrorbefore the plan is sent.A row whose group key is absent joins no group — it is counted separately rather than folded into an existing one, so a missing category never silently merges with a real one.
A group with nothing to average has no mean (
None), while itscountandsumare a real0.min/maxnever come from aNaNrow. ANaNvalue is counted in its group but never becomes that group's extremum.
Reusing one table across several queries
Sending a large table again for every query re-sends the same bytes each time. open_dataset makes a value resident once and returns a handle you reference from Query's dataset argument instead of rows:
Handles are scoped to one worker connection and are never reissued after close_dataset — a stale handle fails with dataset_not_found rather than reading whatever took its place.
See also
Dataframe group-by — the benchmark measuring this same composed engine against DuckDB and Polars.
Make your first query — the governed, hosted
/v1/querysurface (a different feature: server-scoped, resolver-driven, not this local plan builder).Route & execute capabilities — choosing and installing runtime shards.
Last updated
Was this helpful?