Panels
Panels add derived columns alongside the original data — percentages, differences, or percentage change. Each panel adds a level to the column index to distinguish it from the source data.
as_* vs add_*
Flatbread offers two forms for each transform:
as_percentages()— replaces the data with percentagesadd_percentages()— keeps the original data and adds percentages as a separate panel
The same pattern applies to differences (as_differences / add_differences).
Use the as_* form when you only need the derived values. Use the add_*
form when you want both side by side.
Percentages
Replacing data with percentages
as_percentages transforms the values in place. The original counts are gone:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = "species",
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_totals()
.pita.as_percentages()
)
Adding a percentage panel
add_percentages keeps the counts and adds percentages alongside them:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = "species",
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_totals()
.pita.add_percentages()
)
The axis parameter
The axis parameter controls what the percentages are relative to:
0— column totals (each column sums to 100%)1— row totals (each row sums to 100%)2— grand total (the default; entire table sums to 100%)
Rounding
By default, percentages are not rounded (ndigits=-1). Set ndigits to
control decimal places. When rounding, flatbread uses apportioned rounding
by default — this ensures the rounded percentages still sum to the base
value, avoiding the common issue where rounded percentages add up to 99%
or 101%.
The default base=1 produces proportions (0–1). The flatbread-table
viewer automatically formats these as percentages when it detects the
panel label. Use base=100 if you need literal percentage values
(e.g. for export or further calculation).
Differences
add_differences computes the difference between consecutive values
along an axis. This works well with time-based data — here we pivot
sightings by region and season:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = "region",
columns = "season",
values = "count",
aggfunc = "sum",
)
.pita.add_totals()
.pita.add_differences(axis=1)
)
The periods parameter controls how many steps to look back (default 1).
Percentage change
add_pct_change works like add_differences but computes the relative
change instead of the absolute difference:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = "region",
columns = "season",
values = "count",
aggfunc = "sum",
)
.pita.add_totals()
.pita.add_pct_change(axis=1)
)
Percentages and differences have aliases: add_pct, as_pct,
add_diffs, as_diffs.
Combining panels
Multiple panels can be added to the same DataFrame. Flatbread tracks which panels exist and excludes them from subsequent calculations:
df.pita.add_totals().pita.add_percentages().pita.add_differences()
Interleaving
By default, panels are grouped: all data columns first, then all
panel columns. Set interleaf=True to place panel columns next to
their corresponding data columns:
import pandas as pd
import flatbread
result = (
pd.read_json("docs/examples/sightings.json")
.pivot_table(
index = "species",
columns = "region",
values = "count",
aggfunc = "sum",
)
.pita.add_totals()
.pita.add_percentages(axis=0, interleaf=True)
)
Symmetric vs group interleaving
How interleaving works depends on the panel shape. Percentages and differences along axis=0 produce a panel with the same columns as the data — one panel column per data column. Interleaving pairs them one-to-one:
df.pita.add_totals().pita.add_percentages(interleaf=True)
# → Spring | Spring pct | Summer | Summer pct | ...
Differences and percentage change along axis=1 produce fewer columns than the data, since each value compares two adjacent columns. These panels can only be interleaved when the original data has more than one column level (e.g. region and season). In that case, interleaving places the data and diff columns together within each group rather than pairing them one-to-one:
# columns: (region, season)
df.pita.add_differences(axis=1, interleaf=True)
# Coast: Spring | Summer | Autumn | Spring-Summer | Summer-Autumn
# Forest: Spring | Summer | Autumn | Spring-Summer | Summer-Autumn
Panels with the same column structure can be interleaved together,
but the two shapes cannot be mixed. Call interleave() at the end
of the chain, after all panels have been added.