Aggregations
Group rows and summarize them with group_by().agg(), and compute per-group running values with window functions. A group_by followed by agg fuses into a single group_by node in the graph, however many aggregations it carries.
A worked example
This runs against committed data and is executed by the docs test suite:
import flowfile as ff
# One group_by node fuses the grouping and every aggregation.
summary = (
ff.read_csv("data/templates/orders.csv")
.group_by("customer_id")
.agg(
ff.col("order_id").count().alias("n_orders"),
ff.col("quantity").sum().alias("total_qty"),
ff.col("quantity").mean().alias("avg_qty"),
ff.col("quantity").min().alias("min_qty"),
ff.col("quantity").max().alias("max_qty"),
ff.col("quantity").std().alias("std_qty"),
ff.col("quantity").first().alias("first_qty"),
ff.col("quantity").implode().alias("all_qty"),
)
.collect()
)
# Sum every numeric column at once with the all_ selector inside select.
totals = (
ff.read_csv("data/templates/orders.csv")
.select(ff.col("quantity"))
.select(ff.all_().sum())
.collect()
)
# Window functions: rank and running total within each customer.
ranked = (
ff.read_csv("data/templates/orders.csv")
.with_columns(
ff.col("quantity").rank(method="dense", descending=True).over("customer_id").alias("qty_rank"),
ff.col("quantity").cum_sum().over("customer_id").alias("cum_qty"),
)
.collect()
)
The sections below break down each part.
Basic group by
import flowfile as ff
df = ff.FlowFrame({
"category": ["A", "B", "A", "B", "A"],
"value": [10, 20, 30, 40, 50],
"quantity": [1, 2, 3, 4, 5],
})
result = df.group_by("category").agg([
ff.col("value").sum().alias("total_value"),
ff.col("value").mean().alias("avg_value"),
ff.col("quantity").count().alias("count"),
])
# A description shows up on the group_by node in the visual editor.
result = df.group_by("category", description="Group by product category").agg([
ff.col("value").sum().alias("total_value"),
])
Multiple grouping columns
result = df.group_by(["region", "category"]).agg([
ff.col("sales").sum().alias("total_sales"),
ff.col("sales").mean().alias("avg_sales"),
])
Grouping by an expression
# Grouping by an expression emits a polars_code node (not an editable group_by node).
result = df.group_by([
ff.col("date").dt.year().alias("year"),
]).agg([
ff.col("amount").sum(),
])
Aggregating every numeric column
The ff.all_() selector expands to all columns. Use it inside select (not directly inside a native group_by().agg(), which needs a concrete column name per aggregation):
# Sum a whole frame of numeric columns
totals = df.select(ff.numeric()).select(ff.all_().sum())
Available aggregations
| Method | Description |
|---|---|
sum() |
Sum of values |
mean() |
Average value |
median() |
Median value |
min() |
Minimum value |
max() |
Maximum value |
count() |
Count of non-null values |
std() |
Standard deviation |
var() |
Variance |
first() |
First value in group |
last() |
Last value in group |
implode() |
Collect the group's values into a list |
implode, not list
To gather a group's values into a single list column, use implode(). .list is a namespace accessor for existing list columns, not an aggregation.
Window functions
Window functions compute a value per row within a group, without collapsing the frame. Use .over(...):
df = df.with_columns([
ff.col("value").cum_sum().over("category").alias("running_total"),
ff.col("value").rank(descending=True).over("category").alias("rank"),
])
Use cum_sum, not cumsum
The cumulative-sum expression follows the pinned Polars name: cum_sum(). cumsum() raises AttributeError.