great_tables
  • Get Started
  • Examples
  • Reference
  • Blog

Examples

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

islands_mini = (
    pl.from_pandas(islands).sort("size", descending=True)
    .head(10)
)

(
    GT(islands_mini)
    .tab_header(
        title="Large Landmasses of the World",
        subtitle="The top ten largest are presented"
    )
    .tab_stub(rowname_col="name")
    .tab_source_note(source_note="Source: The World Almanac and Book of Facts, 1975, page 406.")
    .tab_source_note(
        source_note=md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
    )
    .tab_stubhead(label="landmass")
    .fmt_integer(columns="size")
)
Large Landmasses of the World
The top ten largest are presented
landmass size
Asia 16,988
Africa 11,506
North America 9,390
South America 6,795
Antarctica 5,500
Europe 3,745
Australia 2,968
Greenland 840
New Guinea 306
Borneo 280
Source: The World Almanac and Book of Facts, 1975, page 406.
Reference: McNeil, D. R. (1977) Interactive Data Analysis. Wiley.
Show the Code
from great_tables import GT, html
from great_tables.data import airquality

airquality_mini = airquality.head(10).assign(Year = 1973)

(
    GT(airquality_mini)
    .tab_header(
        title="New York Air Quality Measurements",
        subtitle="Daily measurements in New York City (May 1-10, 1973)"
    )
    .tab_spanner(
        label="Time",
        columns=["Year", "Month", "Day"]
    )
    .tab_spanner(
        label="Measurement",
        columns=["Ozone", "Solar_R", "Wind", "Temp"]
    )
    .cols_move_to_start(columns=["Year", "Month", "Day"])
    .cols_label(
        Ozone = html("Ozone,<br>ppbV"),
        Solar_R = html("Solar R.,<br>cal/m<sup>2</sup>"),
        Wind = html("Wind,<br>mph"),
        Temp = html("Temp,<br>&deg;F")
    )
)
New York Air Quality Measurements
Daily measurements in New York City (May 1-10, 1973)
Time Measurement
Year Month Day Ozone,
ppbV
Solar R.,
cal/m2
Wind,
mph
Temp,
°F
1973 5 1 41.0 190.0 7.4 67
1973 5 2 36.0 118.0 8.0 72
1973 5 3 12.0 149.0 12.6 74
1973 5 4 18.0 313.0 11.5 62
1973 5 5 14.3 56
1973 5 6 28.0 14.9 66
1973 5 7 23.0 299.0 8.6 65
1973 5 8 19.0 99.0 13.8 59
1973 5 9 8.0 19.0 20.1 61
1973 5 10 194.0 8.6 69
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

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%