Examples

Show the Code
import polars as pl
from great_tables import GT, md, html
from great_tables.data import countrypops

countries_mini = (
    pl.from_pandas(countrypops)
    .filter(pl.col("year") == 2022)
    .sort("population", descending=True)
    .select("country_name", "population")
    .head(10)
)

(
    GT(countries_mini)
    .tab_header(
        title="The World's Most Populous Countries",
        subtitle="The top ten in 2022 are presented"
    )
    .tab_stub(rowname_col="country_name")
    .tab_source_note(
        source_note="Total population counts all residents regardless of legal status or citizenship."
    )
    .tab_source_note(
        source_note=md("Source: [The World Bank](https://data.worldbank.org/indicator/SP.POP.TOTL).")
    )
    .tab_stubhead(label="country")
    .fmt_integer(columns="population")
)
The World's Most Populous Countries
The top ten in 2022 are presented
country population
India 1,417,173,173
China 1,412,175,000
United States 333,287,557
Indonesia 275,501,339
Pakistan 235,824,862
Nigeria 218,541,212
Brazil 215,313,498
Bangladesh 171,186,372
Russian Federation 143,555,736
Mexico 127,504,125
Total population counts all residents regardless of legal status or citizenship.
Source: The World Bank.
Show the Code
from great_tables import GT, html
from great_tables.data import gibraltar

gibraltar_mini = gibraltar.head(10)[["temp", "humidity", "wind_speed", "pressure", "date", "time"]]

(
    GT(gibraltar_mini)
    .tab_header(
        title="Weather at Gibraltar Airport",
        subtitle="Observations from the early hours of May 1, 2023"
    )
    .tab_spanner(
        label="Observed",
        columns=["date", "time"]
    )
    .tab_spanner(
        label="Measurement",
        columns=["temp", "humidity", "wind_speed", "pressure"]
    )
    .cols_move_to_start(columns=["date", "time"])
    .fmt_percent(columns="humidity", decimals=0)
    .cols_label(
        date = "Date",
        time = "Time",
        temp = html("Temp,<br>&deg;C"),
        humidity = "Humidity",
        wind_speed = html("Wind,<br>m s<sup>&minus;1</sup>"),
        pressure = html("Pressure,<br>hPa")
    )
)
Weather at Gibraltar Airport
Observations from the early hours of May 1, 2023
Observed Measurement
Date Time Temp,
°C
Humidity Wind,
m s−1
Pressure,
hPa
2023-05-01 00:20 18.9 68% 6.7 1015.2
2023-05-01 00:50 18.9 73% 7.2 1015.2
2023-05-01 01:20 17.8 77% 6.7 1014.6
2023-05-01 01:50 18.9 73% 6.7 1014.6
2023-05-01 02:20 18.9 68% 6.7 1014.6
2023-05-01 02:50 17.8 73% 6.7 1014.6
2023-05-01 03:20 17.8 73% 7.2 1014.6
2023-05-01 03:50 17.8 73% 6.3 1013.5
2023-05-01 04:20 18.9 64% 4.0 1014.6
2023-05-01 04:50 18.9 64% 3.1 1014.6
Show the Code
from great_tables import GT
from great_tables.data import countrypops
import polars as pl
import polars.selectors as cs

# Get vectors of 2-letter country codes for each region of Oceania
oceania = {
    "Australasia": ["AU", "NZ"],
    "Melanesia": ["NC", "PG", "SB", "VU"],
    "Micronesia": ["FM", "GU", "KI", "MH", "MP", "NR", "PW"],
    "Polynesia": ["PF", "WS", "TO", "TV"],
}

# Create a dictionary mapping country to region (e.g. AU -> Australasia)
country_to_region = {
    country: region for region, countries in oceania.items() for country in countries
}

wide_pops = (
    pl.from_pandas(countrypops)
    .filter(
        pl.col("country_code_2").is_in(list(country_to_region))
        & pl.col("year").is_in([2000, 2010, 2020])
    )
    .with_columns(pl.col("country_code_2").replace(country_to_region).alias("region"))
    .pivot(index=["country_name", "region"], on="year", values="population")
    .sort("2020", descending=True)
)

(
    GT(wide_pops)
    .tab_header(title="Populations of Oceania's Countries in 2000, 2010, and 2020")
    .tab_spanner(label="Total Population", columns=cs.all())
    .tab_stub(rowname_col="country_name", groupname_col="region")
    .fmt_integer()
)
Populations of Oceania's Countries in 2000, 2010, and 2020
Total Population
2000 2010 2020
Australasia
Australia 19,028,802 22,031,750 25,655,289
New Zealand 3,857,700 4,350,700 5,090,200
Melanesia
Papua New Guinea 5,508,297 7,583,269 9,749,640
Solomon Islands 429,978 540,394 691,191
Vanuatu 192,074 245,453 311,685
New Caledonia 213,230 249,750 272,460
Polynesia
French Polynesia 250,927 283,788 301,920
Samoa 184,008 194,672 214,929
Tonga 102,603 107,383 105,254
Tuvalu 9,638 10,550 11,069
Micronesia
Guam 160,188 164,905 169,231
Kiribati 88,826 107,995 126,463
Micronesia (Federated States) 111,709 107,588 112,106
Northern Mariana Islands 80,338 54,087 49,587
Marshall Islands 54,224 53,416 43,413
Palau 19,726 18,540 17,972
Nauru 10,377 10,241 12,315
Show the Code
from great_tables import GT, html
from great_tables.data import towny

towny_mini = (
    towny[["name", "website", "density_2021", "land_area_km2", "latitude", "longitude"]]
    .sort_values("density_2021", ascending=False)
    .head(10)
)

towny_mini["url_name"] = "[" + towny_mini["name"] + "](" + towny_mini["website"] + ")"

towny_mini["location"] = (
    "[map](http://maps.google.com/?ie=UTF8&hq=&ll="
    + towny_mini["latitude"].astype(str)
    + ","
    + towny_mini["longitude"].astype(str)
    + "&z=13)"
)

(
    GT(
        towny_mini[["url_name", "location", "land_area_km2", "density_2021"]],
        rowname_col="url_name",
    )
    .tab_header(
        title="The Municipalities of Ontario",
        subtitle="The top 10 highest population density in 2021",
    )
    .tab_stubhead(label="Municipality")
    .fmt_markdown(columns=["url_name", "location"])
    .fmt_number(columns=["land_area_km2", "density_2021"], decimals=1)
    .cols_label(
        land_area_km2=html("land area, <br>km<sup>2</sup>"),
        density_2021=html("density, <br>people/km<sup>2</sup>"),
    )
)
The Municipalities of Ontario
The top 10 highest population density in 2021
Municipality location land area,
km2
density,
people/km2
Toronto map 631.1 4,427.8
Brampton map 265.9 2,469.0
Mississauga map 292.7 2,452.6
Newmarket map 38.5 2,284.2
Richmond Hill map 100.8 2,004.4
Orangeville map 15.2 1,989.9
Ajax map 66.6 1,900.8
Waterloo map 64.1 1,895.7
Kitchener map 136.8 1,877.7
Guelph map 87.4 1,644.1
Show the Code
from great_tables import GT, html
from great_tables.data import sza
import polars as pl
import polars.selectors as cs

sza_pivot = (
    pl.from_pandas(sza)
    .filter((pl.col("latitude") == "20") & (pl.col("tst") <= "1200"))
    .select(pl.col("*").exclude("latitude"))
    .drop_nulls()
    .pivot(values="sza", index="month", on="tst", sort_columns=True)
)

(
    GT(sza_pivot, rowname_col="month")
    .data_color(
        domain=[90, 0],
        palette=["rebeccapurple", "white", "orange"],
        na_color="white",
    )
    .tab_header(
        title="Solar Zenith Angles from 05:30 to 12:00",
        subtitle=html("Average monthly values at latitude of 20&deg;N."),
    )
    .sub_missing(missing_text="")
)
Solar Zenith Angles from 05:30 to 12:00
Average monthly values at latitude of 20°N.
0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8
Show the Code
from great_tables import GT, html
from great_tables.data import gtcars

cols = ["hp", "hp_rpm", "trq", "trq_rpm", "mpg_c", "mpg_h", "msrp"]
row_labels = {
    "hp": "HP",
    "hp_rpm": "HP RPM",
    "trq": "Torque",
    "trq_rpm": "Torque RPM",
    "mpg_c": "MPG city",
    "mpg_h": "MPG hwy",
    "msrp": "MSRP",
}

gtcars_corr = gtcars[cols].corr().reset_index(names="variable")
gtcars_corr["variable"] = gtcars_corr["variable"].map(row_labels)

(
    GT(gtcars_corr, rowname_col="variable")
    .tab_header(
        title="Correlations Between gtcars Performance Specs",
        subtitle="Pearson correlation across horsepower, torque, fuel economy, and price",
    )
    .fmt_number(columns=cols, decimals=2)
    .data_color(
        columns=cols,
        palette=["#4b6ea9", "white", "#c0392b"],
        domain=[-1, 1],
        na_color="white",
    )
    .cols_label(
        hp="HP",
        hp_rpm=html("HP<br>RPM"),
        trq="Torque",
        trq_rpm=html("Torque<br>RPM"),
        mpg_c=html("MPG<br>city"),
        mpg_h=html("MPG<br>hwy"),
        msrp="MSRP",
    )
    .tab_source_note(source_note="Source: great_tables.data.gtcars")
)
Correlations Between gtcars Performance Specs
Pearson correlation across horsepower, torque, fuel economy, and price
HP HP
RPM
Torque Torque
RPM
MPG
city
MPG
hwy
MSRP
HP 1.00 0.47 0.85 0.47 −0.66 −0.79 0.72
HP RPM 0.47 1.00 0.03 0.79 −0.42 −0.60 0.47
Torque 0.85 0.03 1.00 0.09 −0.45 −0.52 0.53
Torque RPM 0.47 0.79 0.09 1.00 −0.47 −0.63 0.45
MPG city −0.66 −0.42 −0.45 −0.47 1.00 0.84 −0.41
MPG hwy −0.79 −0.60 −0.52 −0.63 0.84 1.00 −0.54
MSRP 0.72 0.47 0.53 0.45 −0.41 −0.54 1.00
Source: great_tables.data.gtcars

View notebook ⬀

Highest Paid Athletes in 2023
Name icon Sport Earnings
Total $M Off field $M Off field %
1 Cristiano Ronaldo Soccer 136.0 90.0
2 Lionel Messi Soccer 130.0 65.0
3 Kylian Mbappé Soccer 120.0 20.0
4 LeBron James Basketball 119.5 75.0
5 Canelo Alvarez Boxing 110.0 10.0
6 Dustin Johnson Golf 107.0 5.0
7 Phil Mickelson Golf 106.0 2.0
8 Stephen Curry Basketball 100.4 52.0
9 Roger Federer Tennis 95.1 95.0

Original table: @LisaHornung_ | Sports icons: Firza Alamsyah | Data: Forbes

View source ⬀     Blog post (R code) ⬀

2023 Mean Carbon Intensity (gCO2eq/kWh) and Power Consumption Breakdown (%)
Zone CO2 Intensity Hydro Nuclear Wind Solar Geothermal Biomass Gas Coal Oil Unknown Hydro Discharge Battery Discharge
Sweden 26 39.1% 26.8% 27.7% 0.1% 0.0% 0.4% 0.4% 0.8% 0.0% 4.6% 0.1% 0.0%
Iceland 28 69.4% 0.0% 0.0% 0.0% 30.6% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0%
Quebec 35 90.1% 2.1% 4.4% 0.0% 0.0% 1.9% 1.4% 0.0% 0.0% 0.0% 0.0% 0.0%
France 46 12.3% 65.4% 10.3% 1.8% 0.0% 1.0% 7.1% 0.3% 0.3% 0.1% 1.4% 0.0%
Ontario 104 23.3% 49.4% 8.7% 0.1% 0.0% 0.2% 18.1% 0.0% 0.0% 0.0% 0.0% 0.0%
New Zealand 106 60.5% 0.0% 7.7% 0.1% 19.0% 0.0% 6.8% 3.7% 0.0% 2.2% 0.0% 0.0%
Finland 107 20.2% 36.5% 24.1% 0.1% 0.0% 6.2% 3.0% 8.1% 0.0% 1.8% 0.0% 0.0%
South Australia 132 0.7% 0.0% 42.6% 33.7% 0.0% 0.0% 13.3% 9.0% 0.0% 0.0% 0.0% 0.7%
Spain 132 17.1% 24.2% 25.1% 8.0% 0.0% 2.0% 18.8% 1.3% 0.2% 0.3% 3.0% 0.0%
Belgium 147 1.3% 39.6% 25.2% 3.6% 0.0% 2.8% 19.4% 1.7% 0.1% 4.9% 1.2% 0.0%
Tasmania 162 49.0% 0.0% 22.6% 10.8% 0.0% 0.0% 1.5% 16.1% 0.0% 0.0% 0.0% 0.0%
East Denmark 184 6.4% 5.5% 48.4% 1.3% 0.0% 16.8% 7.7% 10.8% 1.4% 1.4% 0.4% 0.0%
West Denmark 188 8.8% 2.2% 56.3% 1.6% 0.0% 7.6% 8.5% 13.0% 0.9% 0.4% 0.6% 0.0%
Great Britain 214 3.8% 12.4% 35.9% 2.7% 0.0% 6.2% 35.1% 2.0% 0.0% 1.0% 1.0% 0.0%
Netherlands 218 1.1% 3.9% 46.7% 10.8% 0.0% 4.6% 22.4% 8.6% 0.8% 1.1% 0.2% 0.0%
New York ISO 275 23.7% 22.8% 4.9% 0.0% 0.0% 0.1% 46.9% 0.0% 0.0% 1.6% 0.0% 0.0%
Italy (North) 307 22.7% 14.5% 3.9% 2.9% 0.2% 3.1% 38.4% 1.5% 0.2% 9.3% 3.3% 0.0%
California 328 8.4% 12.7% 7.9% 12.0% 3.0% 1.8% 48.5% 2.1% 0.0% 1.2% 0.0% 2.6%
Germany 389 4.4% 2.8% 39.7% 3.3% 0.0% 8.7% 14.4% 23.3% 0.6% 0.6% 2.1% 0.0%
Ireland 389 3.7% 0.8% 38.5% 0.2% 0.0% 2.5% 42.4% 9.7% 2.0% 0.1% 0.1% 0.0%
Western Australia 417 0.0% 0.0% 14.1% 33.8% 0.0% 0.3% 24.2% 27.1% 0.3% 0.0% 0.0% 0.3%
Texas 432 0.0% 9.1% 22.3% 6.0% 0.0% 0.0% 46.1% 16.1% 0.0% 0.4% 0.0% 0.0%
Alberta 447 1.9% 0.0% 12.4% 1.1% 0.0% 2.5% 70.7% 7.2% 0.0% 4.1% 0.0% 0.0%
Victoria 508 3.9% 0.0% 17.5% 19.0% 0.0% 0.0% 0.3% 59.1% 0.0% 0.0% 0.0% 0.2%
New South Wales 578 3.2% 0.0% 9.5% 23.7% 0.0% 0.2% 0.7% 62.6% 0.0% 0.0% 0.0% 0.1%
Queensland 662 1.9% 0.0% 3.8% 21.1% 0.0% 0.0% 7.2% 65.7% 0.2% 0.0% 0.0% 0.1%
South Africa 685 2.2% 4.3% 5.8% 3.8% 0.0% 0.0% 0.0% 79.9% 2.0% 0.1% 2.0% 0.0%
India (North) 693 9.3% 2.2% 0.1% 10.6% 0.0% 0.0% 1.8% 75.2% 0.0% 0.9% 0.0% 0.0%

Source: api.electricitymap.org | Methodology: https://www.electricitymaps.com/methodology. Some emissions factors are based on IPCC 2014 defaults, while some are based on more accurate regional factors.
All zones are publicly available on the Carbon intensity and emission factors tab via Google docs link

View source ⬀     Notebook ⬀

Show the Code
import polars as pl
import polars.selectors as cs
from great_tables import GT, loc, style

coffee_sales = pl.read_ndjson("./_data/coffee-sales.ndjson")

sel_rev = cs.starts_with("revenue")
sel_prof = cs.starts_with("profit")

# yo

coffee_table = (
    GT(coffee_sales)
    .tab_header("Sales of Coffee Equipment")
    .tab_spanner(label="Revenue", columns=sel_rev)
    .tab_spanner(label="Profit", columns=sel_prof)
    .cols_label(
        revenue_dollars="Amount",
        profit_dollars="Amount",
        revenue_pct="Percent",
        profit_pct="Percent",
        monthly_sales="Monthly Sales",
        icon="",
        product="Product",
    )
    # formatting ----
    .fmt_number(
        columns=cs.ends_with("dollars"),
        compact=True,
        pattern="${x}",
        n_sigfig=3,
    )
    .fmt_percent(columns=cs.ends_with("pct"), decimals=0)
    # style ----
    .tab_style(
        style=style.fill(color="aliceblue"),
        locations=loc.body(columns=sel_rev),
    )
    .tab_style(
        style=style.fill(color="papayawhip"),
        locations=loc.body(columns=sel_prof),
    )
    .tab_style(
        style=style.text(weight="bold"),
        locations=loc.body(rows=pl.col("product") == "Total"),
    )
    .fmt_nanoplot("monthly_sales", plot_type="bar")
    .fmt_image("icon", path="_data/coffee-table-icons/")
    .sub_missing(missing_text="")
)

coffee_table
Sales of Coffee Equipment
Product Revenue Profit Monthly Sales
Amount Percent Amount Percent
Grinder $904K 3% $568K 4%
7650521494596613667748765686607594568751
Moka pot $2.05M 7% $181K 1%
6.87K04.73K4.74K4.79K5.51K6.16K6.62K6.87K6.03K5.30K4.88K4.65K6.28K
Cold brew $289K 1% $242K 2%
2.70K02442494389811.77K2.70K2.61K2.35K1.74K896499244
Filter $404K 1% $70.0K 0%
2.74K02.07K1.81K1.84K2.12K2.25K2.63K2.56K2.37K2.16K2.19K2.07K2.74K
Drip machine $2.63M 9% $1.37M 9%
2.58K02.14K1.62K1.97K2.10K2.58K2.46K2.34K2.32K2.05K1.97K1.84K2.33K
AeroPress $2.60M 9% $1.29M 9%
9.27K06.33K5.20K6.37K7.02K7.91K8.70K8.69K7.80K6.83K6.96K6.88K9.27K
Pour over $846K 3% $365K 2%
2.18K01.56K1.29K1.51K1.69K1.94K2.18K2.14K1.86K1.72K1.81K1.60K2.16K
French press $1.11M 4% $748K 5%
4.82K03.51K2.88K3.35K3.79K3.90K4.10K4.18K4.43K3.28K3.42K3.30K4.82K
Cezve $2.51M 9% $1.97M 13%
17.1K012.2K11.5K11.8K13.6K15.4K16.5K17.1K14.4K13.0K12.9K11.6K15.9K
Chemex $3.14M 11% $818K 6%
7.22K04.94K4.17K5.24K6.00K6.36K6.77K7.11K6.25K5.60K6.08K4.98K7.22K
Scale $3.80M 13% $2.91M 20%
3.18K01.54K1.57K1.68K2.03K2.42K2.55K2.57K2.23K2.04K2.09K1.69K3.18K
Kettle $756K 3% $618K 4%
1.53K01.14K1.02K1.09K1.13K1.41K1.48K1.46K1.30K1.14K1.23K1.19K1.53K
Espresso Machine $8.41M 29% $3.64M 25%
2.58K06868406185982.15K5337979961.00K6688582.58K
Total $29.4M 100% $14.8M 100%