Great Tables v0.15.0: Flags, Icons, and Other Formatting Goodies
Author
Rich Iannone
Published
December 19, 2024
The development of Great Tables is really moving along these days. We just released version 0.15.0 and it adds quite a few nice things to the package. The features we’ll highlight in this post are:
adding flag icons with the new fmt_flag() method
peppering your table cells with Font Awesome icons via fmt_icon()
support for displaying accounting notation with four number-based formatting methods
Let’s look at each of these in turn!
Using fmt_flag() to incorporate country flag icons
When tables contain country-level data, having a more visual representation for a country can help the reader more quickly parse the table contents. The new fmt_flag() method makes this easy to accomplish. You just need to have either two-letter country codes or three-letter country codes in a column.
Here’s an example where country flags, shown as simplified circular icons, can be added to a table with fmt_flag():
This slice of the peeps dataset has country codes in their 3-letter form (i.e., "USA", "SVN", and "CAN") within the country column. So long as they are correct, fmt_flag() will perform the conversion to flag icons. Also, there’s a little bit of interactivity here: when hovering over a flag, the country name will appear as a tooltip!
We have the power to display multiple flag icons within a single cell. To make this happen, the country codes need to be combined in a single string where each code is separated by a comma (e.g., "US,DE,GB"). Here’s an example that uses a portion of the films dataset:
from great_tables import GT, google_fontfrom great_tables.data import filmsimport polars as plfilms_mini = ( pl.from_pandas(films) .filter(pl.col("director") =="Michael Haneke") .with_columns(title=pl.col("title") +" ("+ pl.col("year").cast(pl.String) +")") .select(["title", "run_time", "countries_of_origin"]))( GT(films_mini) .fmt_flag(columns="countries_of_origin") .tab_header(title="In Competition Films by the Michael Haneke") .opt_stylize() .tab_options(column_labels_hidden=True) .opt_table_font(font=google_font("PT Sans")))
In Competition Films by the Michael Haneke
Funny Games (1997)
1h 48m
Code Unknown (2000)
1h 58m
The Piano Teacher (2001)
2h 11m
Caché (2005)
1h 57m
The White Ribbon (2009)
2h 24m
Amour (2012)
2h 7m
Happy End (2017)
1h 47m
The column countries_of_origin has these combined strings for each of the co-production films, where countries are arranged by decreasing level of contribution (e.g., "FR,AT,RO,DE" in the second row). The fmt_flag() method parses these strings into a sequence of flag icons that are displayed in the order provided. Each of the flags is separated by a space character but you can always change that default separator with the sep= argument.
Using fmt_icon() to include Font Awesome icons
The new fmt_icon() method gives you the ability to easily include FontAwesome icons in a table. It uses a similar input/output scheme as with fmt_flag(): provide the short icon name (e.g., "table", "music", "globe", etc.) or a comma-separated list of them, and fmt_icon() will provide the Font Awesome icon in place. Let’s see it in action with an example that uses the metro dataset:
from great_tables import GTfrom great_tables.data import metroimport polars as plmetro_mini = ( pl.from_pandas(metro).tail(10) .with_columns( services = ( pl.when(pl.col("connect_tramway").is_not_null()) .then(pl.lit("train, train-tram")) .otherwise(pl.lit("train")) ) ) .select(["name", "services", "location"]))( GT(metro_mini) .tab_header("Services Available at Select Stations") .fmt_icon(columns="services", sep=" / ") .tab_options(column_labels_hidden=True) .opt_stylize(color="green") .opt_horizontal_padding(scale=3) .opt_align_table_header(align="left"))
Services Available at Select Stations
Porte de Vanves
/
Paris 14th
Saint-Denis—Porte de Paris
/
Saint-Denis
Saint-Denis—Université
/
Saint-Denis
Saint-François-Xavier
Paris 7th
Varenne
Paris 7th
Bibliothèque François Mitterrand
/
Paris 13th
Cour Saint-Émilion
Paris 12th
Olympiades
Paris 13th
Pont Cardinet
Paris 17th
Saint-Ouen
Clichy, Saint-Ouen-sur-Seine
In the code, we added in the icon names "train" and "train-tram" to the services column, and there could either be just the train icon or the pair that includes the tramway service. We wanted a little separation between the icons in the latter case, so sep=" / " was used to place a slash with spacing between any pair of icons. The icons appear here with a black fill color, but that can be changed with the fill_color= argument (and there are several other arguments for controlling style attributes).
For a list of available icons, their names, and what they look like, check out this listing on the FontAwesome website. The icons draw from the Font Awesome ‘free’ set (2000+ icons in total) but are not obtained via the web. Rather, we use the faicons library so that this can be done entirely offline (directly using the SVG icons stored within faicons).
Accounting notation in select numeric formatting methods
For certain types of tables, it may be preferable to use accounting notation for certain numerical figures. This type of notation renders negative values in parentheses while omitting the minus sign. This is often seen for monetary and percentage figures but it’s also sensible for plain numbers in the right context. We’ve added support for accounting notation in four formatting methods:
fmt_number()
fmt_integer()
fmt_currency()
fmt_percent()
Here’s a comprehensive example table that demonstrates how this type of formatting looks.
For the formatting in the final four columns, we use accounting=True to get the values into accounting notation. This is only apparent for the negative values (first row) as the positive values won’t change their appearance, looking the same as they do when accounting=False (the default).
Acknowledgements and how to contact us
We are very grateful for the work that Jerry Wu has done during this release, some of which includes:
enhancing the fmt_image() to support http/https schema in the columns= parameter, and writing an incredible blog post about incorporating images in your tables
improving the save() method, giving it the ability to perform intermediate saves (since the method returns itself)
adding the pipe() method, which operates similarly to that of the Pandas and Polars APIs
all sorts of little QoL fixes
We extend our gratitude also to Alessandro Molina for adding experimental support for pyarrow.Table inputs in this release.