Format values as index characters.
GT.fmt_index(
columns=None,
rows=None,
case="upper",
index_algo="repeat",
pattern="{x}",
locale=None,
)
With numeric values in a gt table, we can transform those to index values, usually based on letters. These characters can be derived from a specified locale and they are intended for ordering (often leaving out characters with diacritical marks). For example, the value 1 would map to "A", 2 to "B", and so on. When the value exceeds the number of characters in the index set, the algorithm set by index_algo determines how to proceed: with "repeat", characters are repeated (e.g., 27 becomes "AA", 28 becomes "BB"); with "excel", Excel-style column naming is used (e.g., 27 becomes "AA", 28 becomes "AB").
Parameters
columns: SelectExpr = None
-
The columns to target. Can either be a single column name or a series of column names provided in a list.
rows: int | list[int] | None = None
-
In conjunction with columns=, we can specify which of their rows should undergo formatting. The default is all rows, resulting in all rows in targeted columns being formatted. Alternatively, we can supply a list of row indices.
case: str = "upper"
-
The case of the resulting index characters. Use "upper" (the default) for uppercase letters or "lower" for lowercase.
index_algo: str = "repeat"
-
The algorithm to use when values exceed the index character set size. "repeat" (the default) repeats characters (1→A, …, 27→AA, 28→BB). "excel" uses Excel-style column naming (1→A, …, 27→AA, 28→AB).
pattern: str = "{x}"
-
A formatting pattern that allows for decoration of the formatted value. The formatted value is represented by {x} and all other characters are interpreted as string literals.
locale: str | None = None
-
An optional locale ID. Currently reserved for future use; index characters default to the English A–Z set regardless of locale.
Returns
GT
-
The GT object is returned. This is the same object that the method is called on so that we can facilitate method chaining.
Examples
Let’s use the towny dataset to create a table of the five smallest census subdivisions by population. The ranking column is formatted as index characters (A through E) and merged with the subdivision name.
import polars as pl
from great_tables import GT, md, data
towny_mini = (
data.pl.towny
.select("name", "census_div", "population_2021")
.group_by("census_div")
.agg(pl.col("population_2021").sum().alias("population"))
.sort("population")
.head(5)
.with_row_index("ranking", offset=1)
.select("ranking", "census_div", "population")
)
(
GT(towny_mini)
.fmt_integer(columns="population")
.fmt_index(columns="ranking", pattern="{x}.")
.cols_merge(columns=["ranking", "census_div"])
.cols_align(align="left", columns="ranking")
.cols_label(
ranking=md("Census<br>Subdivision"),
population=md("Population<br>in 2021"),
)
.tab_header(title=md("The Smallest<br>Census Subdivisions"))
.tab_options(table_width="325px")
)
The Smallest Census Subdivisions |
Census Subdivision |
Population in 2021 |
| A. Manitoulin |
8,906 |
| B. Rainy River |
15,769 |
| C. Sudbury |
18,606 |
| D. Haliburton |
20,571 |
| E. Prince Edward |
25,704 |
Using index_algo="excel" produces Excel-style column naming when values exceed 26. Here we show both algorithms side by side.
import polars as pl
from great_tables import GT
df = pl.DataFrame({
"value": [1, 5, 13, 26, 27, 28, 52, 53, 100],
})
(
GT(
df.with_columns(
repeat=pl.col("value"),
excel=pl.col("value"),
)
)
.fmt_index(columns="repeat", index_algo="repeat")
.fmt_index(columns="excel", index_algo="excel")
.cols_label(value="Value", repeat="Repeat", excel="Excel")
)
| Value |
Repeat |
Excel |
| 1 |
A |
A |
| 5 |
E |
E |
| 13 |
M |
M |
| 26 |
Z |
Z |
| 27 |
AA |
AA |
| 28 |
BB |
AB |
| 52 |
ZZ |
AZ |
| 53 |
AAA |
BA |
| 100 |
VVVV |
CV |