Aggregation
Flatbread provides several methods for adding aggregate rows and columns to a table. All methods leave the original data unmodified and return a new DataFrame.
Subtotals
When your table has a MultiIndex, add_subtotals inserts aggregate rows
at a specified level. Here we pivot sightings by class and species, then
add subtotals per class and an overall total:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = ["class", "species"],
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_subtotals(axis=0, level=0)
.pita.add_totals()
)
The level parameter controls which index level to subtotal by. Level 0
is the outermost level. You can pass multiple levels as a list:
df.pita.add_subtotals(level=[0, 1])
Set include_level_name=True to append the group value to the subtotal
label (e.g. "Subtotals Bird" instead of "Subtotals").
By default, groups with only one row are skipped. Set
skip_single_rows=False to add subtotals for those too.
Custom aggregations
add_agg works like add_totals but with any aggregation function — a
string like 'mean', 'median', 'max', or a callable:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = ["class", "species"],
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_agg("mean", label="Mean")
)
Its counterpart add_subagg is to add_agg what add_subtotals is to
add_totals — it applies the aggregation at a specified MultiIndex level.
The axis parameter
The axis parameter appears on most aggregation methods:
0— aggregate along rows (adds a row)1— aggregate along columns (adds a column)2— both (the default foradd_totals)
add_subtotals defaults to 0. add_totals defaults to 2.
Sorting
Totals and subtotals are placed at the end of their group by default.
sort_totals lets you reposition them — for example, placing them first:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = ["class", "species"],
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_subtotals(axis=0, level=0)
.pita.add_totals()
.pita.sort_totals(totals_last=False)
)
sort_totals uses the labels tracked in df.attrs by flatbread's
operations. If those attrs were lost (some pandas operations strip them),
pass the labels explicitly:
df.pita.sort_totals(labels=["Totals", "Subtotals"])
Dropping totals
drop_totals removes all aggregate rows that flatbread has tracked:
df.pita.add_totals().pita.drop_totals()
This uses the labels stored in df.attrs by flatbread's operations, so
it only removes rows that flatbread added.
Chaining
Operations can be chained freely. Flatbread tracks which labels it has added (totals, subtotals) so that subsequent operations automatically exclude them from calculations. This prevents double-counting:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = ["class", "species"],
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_subtotals(axis=0, level=0)
.pita.add_totals()
.pita.sort_totals()
.pita.add_percentages()
)
Here add_percentages knows to exclude the Subtotals and Totals rows
from its calculation because add_subtotals and add_totals registered
those labels. This is also what ignore_keys controls — you can pass
additional labels to exclude manually when needed.