| Car Performance Review | |||||||
| Using gt-extras functionality | |||||||
| Car | mfr | year | hp | trq | mpg_c | mpg_h | efficiency |
|---|---|---|---|---|---|---|---|
| California | 2015 | 553.0
|
557.0
|
||||
| GTC4Lusso | 2017 | 680.0
|
514.0
|
||||
| FF | 2015 | 652.0
|
504.0
|
||||
| F12Berlinetta | 2015 | 731.0
|
509.0
|
||||
| LaFerrari | 2015 | 949.0
|
664.0
|
||||
| NSX | 2017 | 573.0
|
476.0
|
||||
| GT-R | 2016 | 545.0
|
436.0
|
||||
| Aventador | 2015 | 700.0
|
507.0
|
||||
| Huracan | 2015 | 610.0
|
413.0
|
||||
| Gallardo | 2014 | 550.0
|
398.0
|
||||
| Continental GT | 2016 | 500.0
|
487.0
|
||||
| Granturismo | 2016 | 454.0
|
384.0
|
||||
| Quattroporte | 2016 | 404.0
|
406.0
|
||||
| Ghibli | 2016 | 345.0
|
369.0
|
||||
| 6-Series | 2016 | 315.0
|
330.0
|
||||
| i8 | 2016 | 357.0
|
420.0
|
||||
Examples With Code
Mega Examples
Cars
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
# Setup dataframe
gtcars_mini = gtcars.iloc[5:21].copy().reset_index(drop=True)
gtcars_mini["efficiency"] = gtcars_mini["mpg_c"] / gtcars_mini["hp"] * 100
(
# Start with a standard GT
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label="Car")
.cols_hide(["drivetrain", "hp_rpm", "trq_rpm", "trim", "bdy_style", "msrp", "trsmn", "ctry_origin"])
.cols_align("center")
.tab_header(title="Car Performance Review", subtitle="Using gt-extras functionality")
# Add gt-extras features using gt.pipe()
.pipe(gte.gt_color_box, columns=["hp", "trq"], palette=["lightblue", "darkblue"])
.pipe(gte.gt_plt_dot, category_col="mfr", data_col="efficiency", domain=[0, 0])
.pipe(gte.gt_plt_bar, columns=["mpg_c", "mpg_h"])
.pipe(gte.gt_fa_rating, columns="efficiency")
.pipe(gte.gt_hulk_col_numeric, columns="year", palette="viridis")
.pipe(gte.gt_theme_538)
)NFL 2011 Season
2011 NFL Season at a Glance
Super Bowl XLVI: New York Giants def. New England Patriots
| Team | Record | Scoring | Season Trends | |||
|---|---|---|---|---|---|---|
| Points For vs Points Against | Point Diff | Games | Streak | |||
| AFC East | ||||||
| NE | ![]() |
14-2-0 | 11.9
|
7
|
||
| MIA | ![]() |
10-6-0 | -1.1
|
-1
|
||
| BUF | ![]() |
7-9-0 | 1.3
|
-2
|
||
| NYJ | ![]() |
5-11-0 | -8.4
|
1
|
||
| AFC North | ||||||
| PIT | ![]() |
11-5-0 | 4.5
|
7
|
||
| BAL | ![]() |
8-8-0 | 1.4
|
-2
|
||
| CIN | ![]() |
6-9-1 | 0.6
|
1
|
||
| CLE | ![]() |
1-15-0 | -11.8
|
-1
|
||
| AFC South | ||||||
| TEN | ![]() |
9-7-0 | 0.2
|
1
|
||
| HOU | ![]() |
9-7-0 | -3.1
|
-1
|
||
| IND | ![]() |
8-8-0 | 1.2
|
1
|
||
| JAX | ![]() |
3-13-0 | -5.1
|
-1
|
||
| AFC West | ||||||
| KC | ![]() |
12-4-0 | 4.9
|
2
|
||
| OAK | ![]() |
12-4-0 | 1.9
|
-1
|
||
| DEN | ![]() |
9-7-0 | 2.2
|
1
|
||
| SD | ![]() |
5-11-0 | -0.8
|
-5
|
||
| Source: Lee Sharpe, nflverse | ||||||
| Team | Record | Scoring | Season Trends | |||
|---|---|---|---|---|---|---|
| Points For vs Points Against | Point Diff | Games | Streak | |||
| NFC East | ||||||
| DAL | ![]() |
13-3-0 | 7.2
|
-1
|
||
| NYG | ![]() |
11-5-0 | 1.6
|
1
|
||
| WAS | ![]() |
8-7-1 | 0.8
|
-1
|
||
| PHI | ![]() |
7-9-0 | 2.2
|
2
|
||
| NFC North | ||||||
| GB | ![]() |
10-6-0 | 2.8
|
6
|
||
| DET | ![]() |
9-7-0 | -0.8
|
-3
|
||
| MIN | ![]() |
8-8-0 | 1.2
|
1
|
||
| CHI | ![]() |
3-13-0 | -7.5
|
-4
|
||
| NFC South | ||||||
| ATL | ![]() |
11-5-0 | 8.4
|
4
|
||
| TB | ![]() |
9-7-0 | -0.9
|
1
|
||
| NO | ![]() |
7-9-0 | 0.9
|
-1
|
||
| CAR | ![]() |
6-10-0 | -2.1
|
-2
|
||
| NFC West | ||||||
| SEA | ![]() |
10-5-1 | 3.9
|
1
|
||
| ARI | ![]() |
7-8-1 | 3.5
|
2
|
||
| LA | ![]() |
4-12-0 | -10.6
|
-7
|
||
| SF | ![]() |
2-14-0 | -10.7
|
-1
|
||
| Source: Lee Sharpe, nflverse | ||||||
import polars as pl
from great_tables import GT, md
import gt_extras as gte
nfl_df = pl.read_json("./nfl-season/nfl_2011_stats.json")
def make_gt(df) -> GT:
return (
GT(df, rowname_col="Team", groupname_col="team_division")
.tab_header(
title="2011 NFL Season at a Glance",
subtitle="Super Bowl XLVI: New York Giants def. New England Patriots",
)
.tab_source_note(
md(
'<span style="float: right;">Source: [Lee Sharpe, nflverse](https://github.com/nflverse/nfldata)</span>'
)
)
.tab_stubhead(label="Team")
.tab_spanner(label="Scoring", columns=["Avg PF", "Avg PA", "Point Diff"])
.tab_spanner(label="Season Trends", columns=["Games", "Streak"])
.fmt_number(columns="Point Diff", decimals=1)
.fmt_image("team_logo_espn")
.cols_hide(["Wins", "team_conf", "team_name"])
.cols_align(align="center", columns=["Avg PF", "Avg PA", "Games"])
.cols_move("team_logo_espn", after="Team")
.cols_label({"team_logo_espn": ""})
.pipe(
gte.gt_plt_winloss,
column="Games",
win_color="blue",
loss_color="orange",
tie_color="gray",
height=40,
width=120,
)
.pipe(
gte.gt_fa_rank_change,
column="Streak",
icon_type="turn",
color_up="blue",
color_down="orange",
size=14,
)
.pipe(
gte.gt_plt_dumbbell,
col1="Avg PF",
col2="Avg PA",
col1_color="green",
col2_color="red",
width=300,
height=40,
num_decimals=0,
label="Points For vs Points Against",
font_size=12,
)
.pipe(
gte.gt_color_box,
columns="Point Diff",
palette=["green", "yellow", "red"],
domain=[14, -14]
)
.pipe(gte.gt_highlight_cols, columns="Team", fill="lightgray")
.pipe(gte.gt_highlight_rows, rows="NYG", fill="gold", alpha=0.3)
.pipe(gte.gt_highlight_rows, rows="NE", fill="silver", alpha=0.3)
.pipe(gte.gt_add_divider, columns="Point Diff", color="darkblue", weight=3)
.pipe(gte.gt_theme_538)
)
gt1 = make_gt(nfl_df.head(16))
gt2 = make_gt(nfl_df.slice(16, 16))
gte.gt_two_column_layout(gt1, gt2, table_header_from=1)Gini Coefficient
Setup
import polars as pl
pre_tax_col = "gini_market__age_total"
post_tax_col = "gini_disposable__age_total"
# Read the data
df = pl.read_csv(
"https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-08-05/income_inequality_raw.csv",
schema={
"Entity": pl.String,
"Code": pl.String,
"Year": pl.Int64,
post_tax_col: pl.Float64,
pre_tax_col: pl.Float64,
"population_historical": pl.Int64,
"owid_region": pl.String,
},
null_values=["NA", ""],
)
# Propogate the region field to all rows of that country
df = (
df.sort("Entity")
.group_by("Entity", maintain_order=True)
.agg(
[
pl.col("Code"),
pl.col("Year"),
pl.col(post_tax_col),
pl.col(pre_tax_col),
pl.col("population_historical"),
# Most important action happens here
pl.col("owid_region").fill_null(strategy="backward"),
]
)
.explode(
[
"Code",
"Year",
post_tax_col,
pre_tax_col,
"population_historical",
"owid_region",
]
)
)
# Drop rows where there is a null in either pre-tax or post-tax cols
df = df.drop_nulls(
subset=(
pl.col(post_tax_col),
pl.col(pre_tax_col),
)
)
# Compute the percent reduction in gini coefficient.
df = df.with_columns(
((pl.col(pre_tax_col) - pl.col(post_tax_col)) / pl.col(pre_tax_col) * 100)
.round(2)
.alias("gini_pct_change")
)
# Calculate 5-year benchmark (mean) of percent change for each country
df = df.with_columns(
pl.col("gini_pct_change")
.rolling_mean(window_size=5)
.over(pl.col("Entity"))
.alias("gini_pct_benchmark_5yr")
)
# Select rows with large population in the year 2020, sorted by coefficient post-tax
df = (
# Choose a smaller pop to include more countries
df.filter(pl.col("population_historical").gt(40000000))
.filter(pl.col("Year").eq(2020))
.sort(by=pl.col(post_tax_col))
)
# Scale population
df = df.with_columns((pl.col("population_historical").log10()).alias("pop_log"))
pop_min = df["pop_log"].min() / 1
pop_max = df["pop_log"].max()
# Set up gt-extras icons, scaling population to 1-10 range
df = df.with_columns(
((pl.col("pop_log") - pop_min) / (pop_max - pop_min) * 10 + 1)
.round(0)
.cast(pl.Int64)
.alias("pop_icons")
)
# Format original population value with commas
df = df.with_columns(
pl.col("population_historical").map_elements(
lambda x: f"{int(x):,}" if x is not None else None, return_dtype=pl.String
)
)| Income Inequality Before and After Taxes in 2020 | ||||
| As measured by the Gini coefficient, where 0 is best and 1 is worst | ||||
| Pre-tax to Post-tax Coefficient | Population | Improvement Post Taxes | ||
|---|---|---|---|---|
| Europe | ||||
| France |
65,905,226
|
|||
| Germany |
83,628,661
|
|||
| Spain |
47,679,437
|
|||
| Italy |
59,912,714
|
|||
| United Kingdom |
67,351,806
|
|||
| Asia | ||||
| South Korea |
51,858,440
|
|||
| Turkey |
86,091,644
|
|||
| North America | ||||
| United States |
339,436,106
|
|||
| Mexico |
126,798,998
|
|||
| South America | ||||
| Brazil |
208,660,785
|
|||
from great_tables import GT, html
import gt_extras as gte
# Apply gte.fa_icon_repeat to each entry in the pop_icons column
df_with_icons = df.with_columns(
pl.col("pop_icons").map_elements(
lambda x: gte.fa_icon_repeat(name="person", repeats=int(x)),
return_dtype=pl.String,
)
)
# Generate the table, before gt-extras add-ons
gt = (
GT(df_with_icons, rowname_col="Entity", groupname_col="owid_region")
.tab_header(
"Income Inequality Before and After Taxes in 2020",
"As measured by the Gini coefficient, where 0 is best and 1 is worst",
)
.cols_move("pop_icons", after=pre_tax_col)
.cols_align("left")
.cols_hide(["Year", "pop_log", "population_historical"])
.fmt_flag("Code")
.cols_label(
{
"Code": "",
"gini_pct_change": "Improvement Post Taxes",
"pop_icons": "Population",
}
)
.tab_source_note(
html(
"""
<div>
<strong>Source:</strong> Data from <a href="https://github.com/rfordatascience/tidytuesday">#TidyTuesday</a> (2025-08-05).<br>
<div>
<strong>Dumbbell plot:</strong>
<span style="color:#106ea0;">Blue:</span> post-tax Gini coefficient
<span style="color:#e0b165;">Gold:</span> pre-tax Gini coefficient
<br>
</div>
<strong>Bullet plot:</strong> Percent reduction in Gini after taxes for each country, compared to its 5-year average benchmark.
</div>
"""
)
)
)
# Apply the gt-extras functions via pipe
(
gt.pipe(
gte.gt_plt_dumbbell,
col1=pre_tax_col,
col2=post_tax_col,
col1_color="#e0b165",
col2_color="#106ea0",
dot_border_color="transparent",
num_decimals=2,
width=240,
label="Pre-tax to Post-tax Coefficient",
)
.pipe(
gte.gt_plt_bullet,
"gini_pct_change",
"gini_pct_benchmark_5yr",
fill="#963d4c",
target_color="#3D3D3D",
bar_height=15,
width=200,
)
.pipe(
gte.gt_merge_stack,
col1="pop_icons",
col2="population_historical",
)
.pipe(gte.gt_theme_guardian)
)Plotting
gt_plt_bar
| Car | mfr | year | hp | hp_rpm | trq | trq_rpm | mpg_c | mpg_h |
|---|---|---|---|---|---|---|---|---|
| LaFerrari | Ferrari | 2015 | ||||||
| NSX | Acura | 2017 | ||||||
| GT-R | Nissan | 2016 | ||||||
| Aventador | Lamborghini | 2015 | ||||||
| Huracan | Lamborghini | 2015 | ||||||
| Gallardo | Lamborghini | 2014 | ||||||
| Continental GT | Bentley | 2016 | ||||||
| Granturismo | Maserati | 2016 | ||||||
| Quattroporte | Maserati | 2016 |
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars.loc[
9:17,
["model", "mfr", "year", "hp", "hp_rpm", "trq", "trq_rpm", "mpg_c", "mpg_h"]
]
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label="Car")
.cols_align("center")
.cols_align("left", columns="mfr")
)
gt.pipe(
gte.gt_plt_bar,
columns= ["hp", "hp_rpm", "trq", "trq_rpm", "mpg_c", "mpg_h"]
)gt_plt_bar_pct
| x | autoscale_on | autoscale_off |
|---|---|---|
| 10 | ||
| 20 | ||
| 30 | ||
| 40 |
import polars as pl
from great_tables import GT
import gt_extras as gte
df = pl.DataFrame({"x": [10, 20, 30, 40]}).with_columns(
pl.col("x").alias("autoscale_on"),
pl.col("x").alias("autoscale_off"),
)
gt = GT(df)
(
gt.pipe(
gte.gt_plt_bar_pct,
column=["autoscale_on"],
autoscale=True,
labels=True,
fill="green",
).pipe(
gte.gt_plt_bar_pct,
column=["autoscale_off"],
autoscale=False,
labels=True,
)
)gt_plt_bar_stack
| x | Group 1 | Group 2 | Group 3 |
|---|---|
| Example A | |
| Example B | |
| Example C |
import pandas as pd
from great_tables import GT
import gt_extras as gte
df = pd.DataFrame({
"x": ["Example A", "Example B", "Example C"],
"col": [
[10, 40, 50],
[30, 30, 40],
[50, 20, 30],
],
})
gt = GT(df)
gt.pipe(
gte.gt_plt_bar_stack,
column="col",
palette=["red", "grey", "black"],
labels=["Group 1", "Group 2", "Group 3"],
width=200,
)gt_plt_bullet
| Daily Temp vs Monthly Average | ||
| Temp plot | Temp | |
|---|---|---|
| 5/1 | 67 | |
| 5/2 | 72 | |
| 6/1 | 78 | |
| 6/2 | 74 | |
| 7/1 | 84 | |
| 7/2 | 85 | |
| 8/1 | 81 | |
| 8/2 | 81 | |
| 9/1 | 91 | |
| 9/2 | 92 | |
| Target line shows monthly average temperature | ||
import polars as pl
from great_tables import GT
from great_tables.data import airquality
import gt_extras as gte
air_bullet = (
pl.from_pandas(airquality)
.with_columns(pl.col("Temp").mean().over("Month").alias("target_temp"))
.group_by("Month", maintain_order=True)
.head(2)
.with_columns(
(pl.col("Month").cast(pl.Utf8) + "/" + pl.col("Day").cast(pl.Utf8)).alias(
"Date"
)
)
.select(["Date", "Temp", "target_temp"])
.with_columns(pl.col(["Temp", "target_temp"]).round(1))
)
(
GT(air_bullet, rowname_col="Date")
.tab_header(title="Daily Temp vs Monthly Average")
.tab_source_note("Target line shows monthly average temperature")
## Call gt_plt_bullet
.pipe(
gte.gt_plt_bullet,
data_column="Temp",
target_column="target_temp",
width=200,
fill="tomato",
target_color="darkblue",
keep_data_column=True,
)
.cols_move_to_end("Temp")
.cols_align("left", "Temp plot")
)gt_plt_conf_int
| group | mean | ci_lower | ci_upper | ci |
|---|---|---|---|---|
| A | 5.2 | 3.1 | 7.3 | |
| B | 7.8 | 6.1 | 9.7 | |
| C | 3.4 | 1.8 | 5.0 |
import pandas as pd
from great_tables import GT
import gt_extras as gte
df = pd.DataFrame({
'group': ['A', 'B', 'C'],
'mean': [5.2, 7.8, 3.4],
'ci_lower': [3.1, 6.1, 1.8],
'ci_upper': [7.3, 9.7, 5.0],
'ci': [5.2, 7.8, 3.4],
})
gt = GT(df)
gt.pipe(
gte.gt_plt_conf_int,
column='ci',
ci_columns=['ci_lower', 'ci_upper'],
width=120,
)gt_plt_donut
| Car | mfr | year | hp | hp_rpm | trq | trq_rpm | mpg_c | mpg_h |
|---|---|---|---|---|---|---|---|---|
| LaFerrari | Ferrari | 2015 | ||||||
| NSX | Acura | 2017 | ||||||
| GT-R | Nissan | 2016 | ||||||
| Aventador | Lamborghini | 2015 | ||||||
| Huracan | Lamborghini | 2015 | ||||||
| Gallardo | Lamborghini | 2014 | ||||||
| Continental GT | Bentley | 2016 | ||||||
| Granturismo | Maserati | 2016 | ||||||
| Quattroporte | Maserati | 2016 |
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars.loc[
9:17,
["model", "mfr", "year", "hp", "hp_rpm", "trq", "trq_rpm", "mpg_c", "mpg_h"]
]
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label="Car")
.cols_align("center")
.cols_align("left", columns="mfr")
)
gt.pipe(
gte.gt_plt_donut,
columns=["hp", "hp_rpm", "trq", "trq_rpm", "mpg_c", "mpg_h"],
size=40,
fill="steelblue"
)gt_plt_dot
| Car | mfr | hp |
|---|---|---|
| F12Berlinetta | 731.0 | |
| LaFerrari | 949.0 | |
| NSX | 573.0 | |
| GT-R | 545.0 | |
| Aventador | 700.0 | |
| Huracan | 610.0 | |
| Gallardo | 550.0 | |
| Continental GT | 500.0 | |
| Granturismo | 454.0 | |
| Quattroporte | 404.0 | |
| Ghibli | 345.0 | |
| 6-Series | 315.0 | |
| i8 | 357.0 |
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars.loc[8:20, ["model", "mfr", "hp"]]
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label="Car")
)
gt.pipe(gte.gt_plt_dot, category_col="mfr", data_col="hp")gt_plt_dumbbell
| date | Open to Close ($) |
|---|---|
| 2008-12-03 | |
| 2008-12-04 | |
| 2008-12-05 | |
| 2008-12-08 | |
| 2008-12-09 | |
| 2008-12-10 | |
| 2008-12-11 | |
| 2008-12-12 | |
| 2008-12-15 | |
| Purple: Open Green: Close |
|
import pandas as pd
from great_tables import GT, html, style, loc
from great_tables.data import sp500
import gt_extras as gte
# Trim the data to December 2008
df = sp500[["date", "open", "close"]].copy()
df["date"] = pd.to_datetime(df["date"], errors='coerce')
dec_2008 = df[
(df["date"].dt.month == 12) &
(df["date"].dt.year == 2008)
]
dec_2008 = dec_2008.iloc[::-1].iloc[2:11]
# Make the Great Table
gt = (
GT(dec_2008)
.tab_source_note(html("Purple: Open<br>Green: Close"))
.tab_style(
style=style.text(align="right"),
locations=[loc.source_notes()]
)
)
gt.pipe(
gte.gt_plt_dumbbell,
col1='open',
col2='close',
label = "Open to Close ($)",
num_decimals=0,
width=300,
height=60,
)gt_plt_summary
| Summary Table | ||||||
| 45 rows x 5 cols | ||||||
| Type | Column | Plot Overview | Missing | Mean | Median | SD |
|---|---|---|---|---|---|---|
| Date | 0.0% | — | — | — | ||
| Value | 11.1% | 22.50 | 21.00 | 8.83 | ||
| Category | 22.2% | — | — | — | ||
| Boolean | 0.0% | 0.67 | — | — | ||
| Status | 33.3% | — | — | — | ||
import polars as pl
from great_tables import GT
import gt_extras as gte
from datetime import datetime
df = pl.DataFrame({
"Date": [
datetime(2024, 1, 1),
datetime(2024, 1, 2),
datetime(2024, 1, 7),
datetime(2024, 1, 8),
datetime(2024, 1, 13),
datetime(2024, 1, 16),
datetime(2024, 1, 20),
datetime(2024, 1, 22),
datetime(2024, 2, 1),
] * 5,
"Value": [10, 15, 20, None, 25, 18, 22, 30, 40] * 5,
"Category": ["A", "B", "C", "A", "B", "C", "D", None, None] * 5,
"Boolean": [True, False, True] * 15,
"Status": ["Active", "Inactive", None] * 15,
})
gte.gt_plt_summary(df)gt_plt_winloss
| Team | 10 Games |
|---|---|
| Liverpool | |
| Chelsea | |
| Man City |
from great_tables import GT, md
import gt_extras as gte
import pandas as pd
df = pd.DataFrame(
{
"Team": ["Liverpool", "Chelsea", "Man City"],
"10 Games": [
[1, 1, 0, 1, 0.5, 1, 0, 1, 1, 0],
[0, 0, 1, 0, 1, 1, 1, 0, 1, 1],
[0.5, 1, 0.5, 0, 1, 0, 1, 0.5, 1, 0],
],
}
)
gt = GT(df)
gt.pipe(
gte.gt_plt_winloss,
column="10 Games",
win_color="green",
)Coloring
gt_color_box
| Island | size |
|---|---|
| Asia | 16988
|
| Africa | 11506
|
| North America | 9390
|
| South America | 6795
|
| Antarctica | 5500
|
| Europe | 3745
|
| Australia | 2968
|
| Greenland | 840
|
| New Guinea | 306
|
| Borneo | 280
|
from great_tables import GT
from great_tables.data import islands
import gt_extras as gte
islands_mini = (
islands
.sort_values(by="size", ascending=False)
.head(10)
)
gt = (
GT(islands_mini, rowname_col="name")
.tab_stubhead(label="Island")
)
gt.pipe(gte.gt_color_box, columns="size", palette=["lightblue", "navy"])gt_data_color_by_group
| Color by Group | Color All | |
|---|---|---|
| grp_a | ||
| row_1 | 0.1111 | 0.1111 |
| row_2 | 2.222 | 2.222 |
| row_3 | 33.33 | 33.33 |
| row_4 | 444.4 | 444.4 |
| grp_b | ||
| row_5 | 5550.0 | 5550.0 |
| row_6 | ||
| row_7 | 777000.0 | 777000.0 |
| row_8 | 8880000.0 | 8880000.0 |
Left: gt_data_color_by_group, Right: data_color |
||
from great_tables import GT, md
from great_tables.data import exibble
import gt_extras as gte
gt = (
GT(exibble, rowname_col="row", groupname_col="group")
.cols_hide(columns=None)
.cols_unhide("num")
.cols_label({"num": "Color by Group"})
.pipe(gte.gt_duplicate_column, column="num", dupe_name="Color All")
.tab_source_note(md("Left: `gt_data_color_by_group`, Right: `data_color`"))
)
(
gt
.data_color(columns="Color All", palette="PiYG")
.pipe(gte.gt_data_color_by_group, columns=["num"], palette="PiYG")
)gt_highlight_cols
| Car | year | hp | trq | mpg_h |
|---|---|---|---|---|
| GT | 2017 | 647.0 | 550.0 | 18.0 |
| 458 Speciale | 2015 | 597.0 | 398.0 | 17.0 |
| 458 Spider | 2015 | 562.0 | 398.0 | 17.0 |
| 458 Italia | 2014 | 562.0 | 398.0 | 17.0 |
| 488 GTB | 2016 | 661.0 | 561.0 | 22.0 |
| California | 2015 | 553.0 | 557.0 | 23.0 |
| GTC4Lusso | 2017 | 680.0 | 514.0 | 17.0 |
| FF | 2015 | 652.0 | 504.0 | 16.0 |
from great_tables import GT, md
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars[["model", "year", "hp", "trq", "mpg_h"]].head(8)
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label=md("*Car*"))
)
(
gt
.pipe(gte.gt_highlight_cols, columns="hp")
.pipe(gte.gt_highlight_cols, columns="mpg_h", fill="darkorchid")
)gt_highlight_rows
| Car | year | hp | trq |
|---|---|---|---|
| GT | 2017 | 647.0 | 550.0 |
| 458 Speciale | 2015 | 597.0 | 398.0 |
| 458 Spider | 2015 | 562.0 | 398.0 |
| 458 Italia | 2014 | 562.0 | 398.0 |
| 488 GTB | 2016 | 661.0 | 561.0 |
| California | 2015 | 553.0 | 557.0 |
| GTC4Lusso | 2017 | 680.0 | 514.0 |
| FF | 2015 | 652.0 | 504.0 |
from great_tables import GT, md
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars[["model", "year", "hp", "trq"]].head(8)
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label=md("*Car*"))
)
(
gt
.pipe(gte.gt_highlight_rows, rows=2, fill="#007FFF")
.pipe(gte.gt_highlight_rows, rows=3, fill="chartreuse")
.pipe(gte.gt_highlight_rows, rows=7, fill="#FF007F")
)gt_hulk_col_numeric
| Car | mfr | year | hp | trq | mpg_h |
|---|---|---|---|---|---|
| GT | Ford | 2017 | 647.0 | 550.0 | 18.0 |
| 458 Speciale | Ferrari | 2015 | 597.0 | 398.0 | 17.0 |
| 458 Spider | Ferrari | 2015 | 562.0 | 398.0 | 17.0 |
| 458 Italia | Ferrari | 2014 | 562.0 | 398.0 | 17.0 |
| 488 GTB | Ferrari | 2016 | 661.0 | 561.0 | 22.0 |
| California | Ferrari | 2015 | 553.0 | 557.0 | 23.0 |
| GTC4Lusso | Ferrari | 2017 | 680.0 | 514.0 | 17.0 |
| FF | Ferrari | 2015 | 652.0 | 504.0 | 16.0 |
| F12Berlinetta | Ferrari | 2015 | 731.0 | 509.0 | 16.0 |
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars.loc[0:8, ["model", "mfr", "year", "hp", "trq", "mpg_h"]]
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label="Car")
)
gt.pipe(gte.gt_hulk_col_numeric, columns=["hp", "trq", "mpg_h"])Themes
Setup themes
from great_tables import GT, html
import gt_extras as gte
from great_tables.data import airquality
# Prepare the dataset
airquality_mini = airquality.head(10).assign(Year=1973)
# Create the base table
gt = (
GT(airquality_mini)
.tab_header(
title="Default Theme",
subtitle="New York Air Quality Measurements",
)
.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>°F"),
)
)
gt| Default Theme | ||||||
| New York Air Quality Measurements | ||||||
| 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 | |
gt_theme_538
| FiveThirtyEight Theme | ||||||
| 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 | |
gt = gt.tab_header(title="FiveThirtyEight Theme")
gt.pipe(gte.gt_theme_538)gt_theme_espn
| ESPN Theme | ||||||
| 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 | |
gt = gt.tab_header(title="ESPN Theme")
gt.pipe(gte.gt_theme_espn)gt_theme_guardian
| Guardian Theme | ||||||
| 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 | |
gt = gt.tab_header(title="Guardian Theme")
gt.pipe(gte.gt_theme_guardian)gt_theme_nytimes
| NYTimes Theme | ||||||
| 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 | |
gt = gt.tab_header(title="NYTimes Theme")
gt.pipe(gte.gt_theme_nytimes)gt_theme_excel
| Excel Theme | ||||||
| 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 | |
gt = gt.tab_header(title="Excel Theme")
gt.pipe(gte.gt_theme_excel)gt_theme_dot_matrix
| Dot Matrix Theme | ||||||
| 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 | |
gt = gt.tab_header(title="Dot Matrix Theme")
gt.pipe(gte.gt_theme_dot_matrix)gt_theme_dark
| Dark Theme | ||||||
| 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 | |
gt = gt.tab_header(title="Dark Theme")
gt.pipe(gte.gt_theme_dark)gt_theme_pff
| PFF Theme | ||||||
| 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 | |
gt = gt.tab_header(title="PFF Theme")
gt.pipe(gte.gt_theme_pff)Icons and Images
add_text_img
| Points | Assists | |
|---|---|---|
Josh Hart
|
1051 | 453 |
Jalen Brunson
|
1690 | 475 |
| Images and data courtesy of ESPN | ||
import pandas as pd
from great_tables import GT, md, html
import gt_extras as gte
df = pd.DataFrame(
{
"Player": ["Josh Hart", "Jalen Brunson"],
"Points": [1051, 1690],
"Assists": [453, 475],
}
)
hart_img = gte.add_text_img(
text="Josh Hart",
img_url="https://a.espncdn.com/combiner/i?img=/i/headshots/nba/players/full/3062679.png",
)
brunson_img = gte.add_text_img(
text="Jalen Brunson",
img_url="https://a.espncdn.com/combiner/i?img=/i/headshots/nba/players/full/3934672.png",
)
df["Player"] = [hart_img, brunson_img]
gt = (
GT(df, rowname_col="Player")
.tab_source_note(md("Images and data courtesy of [ESPN](https://www.espn.com)"))
)
gtfa_icon_repeat
| World Population in 2020 | ||
| Each person icon represents ~10 million people | ||
| Country | Population | People |
|---|---|---|
| United States | 331,511,512 | |
| Brazil | 213,196,304 | |
| Mexico | 125,998,302 | |
| France | 67,571,107 | |
| Colombia | 50,930,662 | |
| Poland | 37,899,070 | |
| Ecuador | 17,588,595 | |
| Haiti | 11,306,801 | |
| Switzerland | 8,638,167 | |
import pandas as pd
from great_tables import GT
from great_tables.data import countrypops
import gt_extras as gte
countries_2020 = (
countrypops
.query("year == 2020")
.sort_values("population", ascending=False)
.iloc[[2, 5, 10, 20, 28, 38, 65, 80, 98]]
)
# Scale: 1 icon = 10 million people
def create_population_icons(population):
icon_count = max(1, round(population / 10_000_000))
return gte.fa_icon_repeat(
name="person",
repeats=icon_count,
fill="cornflowerblue",
)
# Prepare the data
df = pd.DataFrame({
"Country": countries_2020["country_name"],
"Population": countries_2020["population"],
"People": [create_population_icons(pop) for pop in countries_2020["population"]],
})
(
GT(df)
.tab_header(
title="World Population in 2020",
subtitle="Each person icon represents ~10 million people"
)
.fmt_number(
columns="Population",
decimals=0
)
)gt_fa_rank_change
| name | 1996_2001 | 2001_2006 | 2006_2011 |
|---|---|---|---|
| Addington Highlands | -0.0111
|
0.0458
|
0.002
|
| Adelaide Metcalfe | 0.0067
|
-0.0044
|
-0.0341
|
| Adjala-Tosorontio | 0.0773
|
0.0608
|
-0.0086
|
| Admaston/Bromley | -0.0046
|
-0.0382
|
0.0471
|
| Ajax | 0.1447
|
0.2226
|
0.2155
|
| Alberton | -0.0691
|
0.0021
|
-0.0981
|
| Alfred and Plantagenet | 0.0334
|
0.0071
|
0.0626
|
| Algonquin Highlands | 0.083
|
0.0816
|
0.1063
|
| Alnwick/Haldimand | 0.0575
|
0.1008
|
0.0283
|
| Amaranth | 0.0928
|
0.0199
|
0.0307
|
from great_tables import GT
from great_tables.data import towny
import gt_extras as gte
mini_towny = towny.head(10)
gt = GT(mini_towny).cols_hide(None).cols_unhide("name")
columns = [
"pop_change_1996_2001_pct",
"pop_change_2001_2006_pct",
"pop_change_2006_2011_pct",
]
for col in columns:
gt = (
gt
.cols_align(columns=col, align="center")
.cols_unhide(col)
.cols_label({col: col[11:20]})
.pipe(
gte.gt_fa_rank_change,
column=col,
neutral_range=[-0.01, 0.01],
)
)
gtgt_fa_rating
| Car | mfr | hp | trq | mpg_c | rating |
|---|---|---|---|---|---|
| F12Berlinetta | Ferrari | 731.0 | 509.0 | 11.0 | |
| LaFerrari | Ferrari | 949.0 | 664.0 | 12.0 | |
| NSX | Acura | 573.0 | 476.0 | 21.0 | |
| GT-R | Nissan | 545.0 | 436.0 | 16.0 | |
| Aventador | Lamborghini | 700.0 | 507.0 | 11.0 | |
| Huracan | Lamborghini | 610.0 | 413.0 | 16.0 | |
| Gallardo | Lamborghini | 550.0 | 398.0 | 12.0 | |
| Continental GT | Bentley | 500.0 | 487.0 | 15.0 |
from random import randint
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = (
gtcars
.loc[8:15, ["model", "mfr", "hp", "trq", "mpg_c"]]
.assign(rating=[randint(1, 5) for _ in range(8)])
)
gt = (
GT(gtcars_mini, rowname_col="model")
.tab_stubhead(label="Car")
)
gt.pipe(gte.gt_fa_rating, columns="rating", name="star")gt_fmt_img_circle
| @machow | @rich-iannone | @juleswg23 |
|---|---|---|
import polars as pl
from great_tables import GT
import gt_extras as gte
rich_avatar = "https://avatars.githubusercontent.com/u/5612024?v=4"
michael_avatar = "https://avatars.githubusercontent.com/u/2574498?v=4"
jules_avatar = "https://avatars.githubusercontent.com/u/54960783?v=4"
df = pl.DataFrame({"@machow": [michael_avatar], "@rich-iannone": [rich_avatar], "@juleswg23": [jules_avatar]})
(
GT(df)
.cols_align("center")
.opt_stylize(color="green", style=6)
.pipe(gte.gt_fmt_img_circle, height=80)
)img_header
Josh Hart
|
Jalen Brunson
|
Mikal Bridges
|
|
|---|---|---|---|
| Points | 1051 | 1690 | 1444 |
| Rebounds | 737 | 187 | 259 |
| Assists | 453 | 475 | 306 |
| Blocks | 27 | 8 | 43 |
| Steals | 119 | 60 | 75 |
| Images and data courtesy of ESPN | |||
import pandas as pd
from great_tables import GT, md
import gt_extras as gte
df = pd.DataFrame(
{
"Category": ["Points", "Rebounds", "Assists", "Blocks", "Steals"],
"Hart": [1051, 737, 453, 27, 119],
"Brunson": [1690, 187, 475, 8, 60],
"Bridges": [1444, 259, 306, 43, 75],
}
)
hart_header = gte.img_header(
label="Josh Hart",
img_url="https://a.espncdn.com/combiner/i?img=/i/headshots/nba/players/full/3062679.png",
)
brunson_header = gte.img_header(
label="Jalen Brunson",
img_url="https://a.espncdn.com/combiner/i?img=/i/headshots/nba/players/full/3934672.png",
)
bridges_header = gte.img_header(
label="Mikal Bridges",
img_url="https://a.espncdn.com/combiner/i?img=/i/headshots/nba/players/full/3147657.png",
)
gt = (
GT(df, rowname_col="Category")
.tab_source_note(md("Images and data courtesy of [ESPN](https://www.espn.com)"))
.cols_label(
{
"Hart": hart_header,
"Brunson": brunson_header,
"Bridges": bridges_header,
}
)
)
gtUtilities
fmt_pct_extra
| name | Population Change | ||
|---|---|---|---|
| '96-'01 | '01-'06 | '06-'11 | |
| Whitchurch-Stouffville | 11.6% | 6.7% | 54.3% |
| White River | <5% | -15.3% | -27.8% |
| Whitestone | 6.4% | 20.8% | -10.9% |
| Whitewater | <5% | <5% | <5% |
| Wilmot | 7.5% | 15.0% | 12.4% |
| Windsor | 5.4% | <5% | <5% |
| Wollaston | -5.6% | 7.5% | <5% |
| Woodstock | <5% | 8.3% | 5.4% |
| Woolwich | 5.1% | 8.0% | 17.7% |
| Zorra | <5% | <5% | <5% |
from great_tables import GT
from great_tables.data import towny
import gt_extras as gte
towny_mini = towny[
[
"name",
"pop_change_1996_2001_pct",
"pop_change_2001_2006_pct",
"pop_change_2006_2011_pct",
]
].tail(10)
gt = (
GT(towny_mini)
.tab_spanner(label="Population Change", columns=[1, 2, 3])
.cols_label(
pop_change_1996_2001_pct="'96-'01",
pop_change_2001_2006_pct="'01-'06",
pop_change_2006_2011_pct="'06-'11",
)
)
gt.pipe(
gte.fmt_pct_extra,
columns=[1, 2, 3],
threshold=5,
color="green",
)gt_add_divider
| name_given | Location | phone_number | Body Measurements | ||
|---|---|---|---|---|---|
| address | city | height_cm | weight_kg | ||
| Ruth | 4299 Bobcat Drive | Baileys Crossroads | 240-783-7630 | 153 | 76.4 |
| Peter | 3705 Hidden Pond Road | Red Boiling Springs | 615-699-3517 | 175 | 74.9 |
| Fanette | 4200 Swick Hill Street | New Orleans | 985-205-2970 | 167 | 61.6 |
| Judyta | 2287 Cherry Ridge Drive | Oakfield | 585-948-7790 | 156 | 54.5 |
| Leonard | 1496 Hillhaven Drive | Los Angeles | 323-857-6576 | 177 | 113.2 |
| Maymun | 4088 Barnes Avenue | Hamilton | 513-738-1936 | 172 | 88.4 |
import pandas as pd
from great_tables import GT
from great_tables.data import peeps
import gt_extras as gte
peeps_mini = peeps.head(6)
gt = (
GT(peeps_mini)
.cols_hide([
"name_family", "postcode", "country", "country_code",
"dob", "gender", "state_prov", "email_addr",
])
.tab_spanner("Location", ["address", "city"])
.tab_spanner("Body Measurements", ["height_cm", "weight_kg"])
)
gt.pipe(
gte.gt_add_divider,
columns="name_given",
color="#FFB90F",
divider_style="double",
weight=8,
).pipe(
gte.gt_add_divider,
columns="phone_number",
color="purple",
sides=["right", "left"],
weight=5,
)gt_duplicate_column
| mfr | model | year | hp_dupe | hp |
|---|---|---|---|---|
| Ford | GT | 2017 | 647.0 | 647.0 |
| Ferrari | 458 Speciale | 2015 | 597.0 | 597.0 |
| Ferrari | 458 Spider | 2015 | 562.0 | 562.0 |
| Ferrari | 458 Italia | 2014 | 562.0 | 562.0 |
| Ferrari | 488 GTB | 2016 | 661.0 | 661.0 |
from great_tables import GT
from great_tables.data import gtcars
import gt_extras as gte
gtcars_mini = gtcars[["mfr", "model", "year", "hp"]].head(5)
gt = GT(gtcars_mini)
(
gt.pipe(
gte.gt_duplicate_column,
column="hp",
after="year",
).pipe(
gte.gt_highlight_cols,
["hp", "hp_dupe"],
fill="tan",
).pipe(
gte.gt_add_divider,
columns=["hp_dupe"],
include_labels=False,
)
)gt_merge_stack
| team_abbr | team_wordmark | |
|---|---|---|
| NFC | ||
Cardinals
NFC West
|
ARI | ![]() |
Falcons
NFC South
|
ATL | ![]() |
Panthers
NFC South
|
CAR | ![]() |
Bears
NFC North
|
CHI | ![]() |
| AFC | ||
Ravens
AFC North
|
BAL | ![]() |
Bills
AFC East
|
BUF | ![]() |
Bengals
AFC North
|
CIN | ![]() |
Browns
AFC North
|
CLE | ![]() |
import pandas as pd
from great_tables import GT
import gt_extras as gte
df = pd.read_csv("../assets/teams_colors_logos.csv")
df = (df.filter(items=["team_nick", "team_abbr", "team_conf", "team_division", "team_wordmark"]).head(8))
gt = GT(df, groupname_col="team_conf", rowname_col="team_nick")
gt = gt.fmt_image(columns="team_wordmark")
gt.pipe(
gte.gt_merge_stack,
col1="team_nick",
col2="team_division",
)gt_two_column_layout
Joined Table
| name_given | address |
|---|---|
| Ruth | 4299 Bobcat Drive |
| Peter | 3705 Hidden Pond Road |
| Fanette | 4200 Swick Hill Street |
| Judyta | 2287 Cherry Ridge Drive |
| Leonard | 1496 Hillhaven Drive |
| Maymun | 4088 Barnes Avenue |
| name_given | address |
|---|---|
| Alma | 4897 Duffy Street |
| Mariana | 2016 Kovar Road |
| Ning | 3892 Bel Meadow Drive |
| Martin | 1850 Valley Lane |
| Cendrillon | Rue de Liège 466 |
| Adélaïde | Orchideeenlaan 470 |
from great_tables import GT
import gt_extras as gte
from great_tables.data import peeps
df1 = peeps.loc[0:5, ["name_given", "address"]]
df2 = peeps.loc[6:11, ["name_given", "address"]]
gt1 = GT(df1).tab_header(title="Joined Table")
gt2 = GT(df2)
gte.gt_two_column_layout(gt1, gt2, table_header_from=1)with_hyperlink
import pandas as pd
from great_tables import GT
import gt_extras as gte
df = pd.DataFrame(
{
"name": ["Great Tables", "Plotnine", "Quarto"],
"url": [
"https://posit-dev.github.io/great-tables/",
"https://plotnine.org/",
"https://quarto.org/",
],
"github_stars": [2334, 4256, 4628],
"repo_url": [
"https://github.com/posit-dev/great-tables",
"https://github.com/has2k1/plotnine",
"https://github.com/quarto-dev/quarto-cli",
],
}
)
df["Package"] = [
gte.with_hyperlink(name, url)
for name, url in zip(df["name"], df["url"])
]
df["Github Stars"] = [
gte.with_hyperlink(github_stars, repo_url, new_tab=False)
for github_stars, repo_url in zip(df["github_stars"], df["repo_url"])
]
GT(df[["Package", "Github Stars"]]).tab_header("Click the Links!")with_tooltip
| Hover for Tooltip | |
| Package | Designed for |
|---|---|
| Great Tables | Tabling |
| Plotnine | Plotting |
| Quarto | Notebooking |
import pandas as pd
from great_tables import GT
import gt_extras as gte
df = pd.DataFrame(
{
"name": ["Great Tables", "Plotnine", "Quarto"],
"Description": [
"Absolutely Delightful Table-making in Python",
"A grammar of graphics for Python",
"An open-source scientific and technical publishing system",
],
"Designed for": ["Tabling", "Plotting", "Notebooking"]
}
)
df["Package"] = [
gte.with_tooltip(name, description, color = "none")
for name, description in zip(df["name"], df["Description"])
]
GT(df[["Package", "Designed for"]]).tab_header("Hover for Tooltip")






































