great-tables

Great Tables Publication-Quality Tables Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "great-tables" with this command: npx skills add vamseeachanta/workspace-hub/vamseeachanta-workspace-hub-great-tables

Great Tables Publication-Quality Tables Skill

Master Great Tables for creating beautiful, publication-quality tables in Python with rich styling, conditional formatting, and export capabilities. Inspired by R's gt package.

When to Use This Skill

USE Great Tables when:

  • Publication tables - Creating tables for reports, papers, or presentations

  • Data presentation - Professional display of analysis results

  • Conditional formatting - Highlighting patterns with colors and icons

  • Complex layouts - Multi-level headers, grouped rows, footnotes

  • HTML reports - Interactive tables for web-based reports

  • Quick formatting - Need polished tables without manual styling

  • Dashboard components - Tables in Streamlit/Dash applications

  • Export requirements - Need PNG or PDF output

DON'T USE Great Tables when:

  • Large datasets - Over 1000 rows for display (use pagination)

  • Interactive editing - Need editable cells (use Streamlit data_editor)

  • Real-time updates - Streaming data display

  • Complex interactivity - Sorting, filtering (use DataTables or AG Grid)

  • Raw data exploration - Use pandas display or ydata-profiling

Prerequisites

Basic installation

pip install great_tables

With all optional dependencies

pip install great_tables pandas polars

For image export (PNG/PDF)

pip install great_tables webshot

Using uv (recommended)

uv pip install great_tables pandas polars

Verify installation

python -c "from great_tables import GT; print('Great Tables ready!')"

Core Capabilities

  1. Basic Table Creation

Simplest Usage:

from great_tables import GT import pandas as pd

Create sample data

df = pd.DataFrame({ "Name": ["Alice", "Bob", "Charlie", "Diana"], "Department": ["Engineering", "Marketing", "Engineering", "Sales"], "Salary": [95000, 78000, 88000, 92000], "Years": [5, 3, 4, 6] })

Create basic table

table = GT(df)

Display (in Jupyter) or save

table.save("basic_table.html")

With Title and Subtitle:

from great_tables import GT, md import pandas as pd

df = pd.DataFrame({ "Product": ["Widget A", "Widget B", "Gadget X", "Gadget Y"], "Revenue": [150000, 220000, 180000, 95000], "Units": [1500, 2200, 900, 950], "Growth": [0.12, 0.25, 0.08, -0.05] })

table = ( GT(df) .tab_header( title="Q4 2025 Sales Performance", subtitle="Product line revenue and growth metrics" ) )

table.save("sales_table.html")

With Source Notes:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Country": ["USA", "UK", "Germany", "Japan"], "GDP_Trillion": [25.5, 3.1, 4.2, 4.9], "Population_Million": [331, 67, 83, 125] })

table = ( GT(df) .tab_header( title="World Economic Indicators", subtitle="Top economies by GDP" ) .tab_source_note( source_note="Source: World Bank, 2024" ) .tab_source_note( source_note="GDP in trillion USD" ) )

table.save("economy_table.html")

  1. Column Formatting

Numeric Formatting:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Item": ["Product A", "Product B", "Product C"], "Price": [29.99, 149.50, 9.99], "Revenue": [1500000, 2250000, 890000], "Margin": [0.35, 0.42, 0.28], "Units": [50000, 15000, 89000] })

table = ( GT(df) .tab_header(title="Product Metrics")

# Format as currency
.fmt_currency(
    columns="Price",
    currency="USD"
)

# Format large numbers with suffixes
.fmt_number(
    columns="Revenue",
    use_seps=True,
    decimals=0
)

# Format as percentage
.fmt_percent(
    columns="Margin",
    decimals=1
)

# Format with thousand separators
.fmt_integer(
    columns="Units",
    use_seps=True
)

)

table.save("numeric_formatting.html")

Date and Time Formatting:

from great_tables import GT import pandas as pd from datetime import datetime, date

df = pd.DataFrame({ "Event": ["Launch", "Update", "Maintenance", "Release"], "Date": [ date(2025, 1, 15), date(2025, 3, 22), date(2025, 6, 1), date(2025, 9, 30) ], "Timestamp": [ datetime(2025, 1, 15, 9, 0), datetime(2025, 3, 22, 14, 30), datetime(2025, 6, 1, 2, 0), datetime(2025, 9, 30, 10, 0) ] })

table = ( GT(df) .tab_header(title="Product Timeline")

# Format date
.fmt_date(
    columns="Date",
    date_style="day_month_year"
)

# Format datetime
.fmt_datetime(
    columns="Timestamp",
    date_style="yMd",
    time_style="Hm"
)

)

table.save("date_formatting.html")

Custom Number Formatting:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Metric": ["Users", "Revenue", "Conversion", "Avg Order"], "Value": [1234567, 5678901.23, 0.0342, 156.789] })

table = ( GT(df) .tab_header(title="Dashboard Metrics")

# Custom suffixes for large numbers
.fmt_number(
    columns="Value",
    rows=[0],  # First row only
    compact=True  # Use K, M, B suffixes
)

# Currency for second row
.fmt_currency(
    columns="Value",
    rows=[1],
    currency="USD",
    decimals=0
)

# Percentage for third row
.fmt_percent(
    columns="Value",
    rows=[2],
    decimals=2
)

# Standard number for fourth row
.fmt_currency(
    columns="Value",
    rows=[3],
    currency="USD",
    decimals=2
)

)

table.save("custom_formatting.html")

  1. Styling and Colors

Background Colors:

from great_tables import GT from great_tables import style, loc import pandas as pd

df = pd.DataFrame({ "Category": ["Electronics", "Clothing", "Food", "Home"], "Q1": [150000, 95000, 120000, 85000], "Q2": [180000, 88000, 135000, 92000], "Q3": [165000, 102000, 128000, 78000], "Q4": [210000, 115000, 145000, 105000] })

table = ( GT(df) .tab_header(title="Quarterly Sales by Category")

# Style header row
.tab_style(
    style=style.fill(color="#4a86e8"),
    locations=loc.column_labels()
)
.tab_style(
    style=style.text(color="white", weight="bold"),
    locations=loc.column_labels()
)

# Alternate row colors
.tab_style(
    style=style.fill(color="#f3f3f3"),
    locations=loc.body(rows=[1, 3])  # Even rows
)

# Highlight specific cell
.tab_style(
    style=style.fill(color="#90EE90"),
    locations=loc.body(columns="Q4", rows=[0])  # Highest Q4
)

)

table.save("styled_table.html")

Text Styling:

from great_tables import GT from great_tables import style, loc import pandas as pd

df = pd.DataFrame({ "Rank": [1, 2, 3, 4, 5], "Company": ["TechCorp", "DataInc", "CloudSoft", "AILabs", "DevHub"], "Revenue_B": [125.4, 98.2, 87.5, 76.3, 65.8], "Change": [0.15, 0.08, -0.03, 0.22, -0.12] })

table = ( GT(df) .tab_header(title="Top Companies by Revenue")

# Bold first column
.tab_style(
    style=style.text(weight="bold"),
    locations=loc.body(columns="Rank")
)

# Italic company names
.tab_style(
    style=style.text(style="italic"),
    locations=loc.body(columns="Company")
)

# Color positive/negative changes
.tab_style(
    style=style.text(color="green"),
    locations=loc.body(columns="Change", rows=[0, 1, 3])  # Positive
)
.tab_style(
    style=style.text(color="red"),
    locations=loc.body(columns="Change", rows=[2, 4])  # Negative
)

# Format numbers
.fmt_currency(columns="Revenue_B", currency="USD", decimals=1)
.fmt_percent(columns="Change", decimals=1)

)

table.save("text_styled.html")

Borders and Spacing:

from great_tables import GT from great_tables import style, loc import pandas as pd

df = pd.DataFrame({ "Section": ["Introduction", "Methods", "Results", "Discussion"], "Pages": [5, 12, 18, 8], "Figures": [2, 6, 15, 3], "Tables": [0, 3, 8, 1] })

table = ( GT(df) .tab_header(title="Manuscript Structure")

# Add border below header
.tab_style(
    style=style.borders(sides="bottom", color="black", weight="2px"),
    locations=loc.column_labels()
)

# Add border below last row
.tab_style(
    style=style.borders(sides="bottom", color="black", weight="2px"),
    locations=loc.body(rows=[-1])
)

# Cell padding
.tab_options(
    data_row_padding="10px",
    column_labels_padding="12px"
)

)

table.save("bordered_table.html")

  1. Conditional Formatting

Color Scales:

from great_tables import GT from great_tables import style, loc from great_tables.data import countrypops import pandas as pd

Sample heatmap data

df = pd.DataFrame({ "Month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], "North": [85, 92, 88, 95, 91, 97], "South": [72, 78, 81, 75, 82, 88], "East": [90, 85, 92, 89, 94, 91], "West": [68, 75, 79, 82, 78, 85] })

table = ( GT(df) .tab_header(title="Regional Performance Scores")

# Apply color scale to data columns
.data_color(
    columns=["North", "South", "East", "West"],
    palette=["#FF6B6B", "#FFEB3B", "#4CAF50"],  # Red -> Yellow -> Green
    domain=[60, 100]
)

)

table.save("color_scale.html")

Conditional Icons:

from great_tables import GT, html import pandas as pd

df = pd.DataFrame({ "Metric": ["Revenue", "Users", "Conversion", "NPS"], "Current": [1250000, 85000, 3.2, 72], "Previous": [1180000, 78000, 3.5, 68], "Change_Pct": [5.9, 9.0, -8.6, 5.9] })

def trend_icon(value): """Return trend icon based on value.""" if value > 0: return html('<span style="color: green;">&#9650;</span>') # Up arrow elif value < 0: return html('<span style="color: red;">&#9660;</span>') # Down arrow else: return html('<span style="color: gray;">&#9654;</span>') # Right arrow

Add trend column

df["Trend"] = df["Change_Pct"].apply(trend_icon)

table = ( GT(df) .tab_header(title="Key Metrics Dashboard")

.fmt_number(columns="Current", use_seps=True, decimals=0)
.fmt_number(columns="Previous", use_seps=True, decimals=0)
.fmt_percent(columns="Change_Pct", decimals=1, scale_values=False)

)

table.save("conditional_icons.html")

Bar Charts in Cells:

from great_tables import GT, html import pandas as pd

df = pd.DataFrame({ "Product": ["Alpha", "Beta", "Gamma", "Delta", "Epsilon"], "Sales": [85000, 120000, 65000, 95000, 110000], "Target": [100000, 100000, 100000, 100000, 100000] })

def create_bar(value, max_value=150000): """Create inline bar chart.""" width = min(value / max_value * 100, 100) color = "#4CAF50" if value >= 100000 else "#FF9800" return html(f''' <div style="background: #eee; width: 100px; height: 20px;"> <div style="background: {color}; width: {width}%; height: 100%;"></div> </div> ''')

df["Progress"] = df["Sales"].apply(create_bar)

table = ( GT(df) .tab_header(title="Sales Progress by Product") .fmt_number(columns="Sales", use_seps=True, decimals=0) .fmt_number(columns="Target", use_seps=True, decimals=0) )

table.save("bar_charts.html")

  1. Grouped Rows and Columns

Row Groups:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Region": ["North", "North", "South", "South", "East", "East", "West", "West"], "Product": ["Widget", "Gadget", "Widget", "Gadget", "Widget", "Gadget", "Widget", "Gadget"], "Sales": [45000, 32000, 38000, 41000, 52000, 28000, 35000, 39000], "Units": [450, 160, 380, 205, 520, 140, 350, 195] })

table = ( GT(df, groupname_col="Region") # Group by Region .tab_header( title="Sales by Region and Product", subtitle="Q4 2025 Performance" ) .fmt_currency(columns="Sales", currency="USD", decimals=0) .fmt_integer(columns="Units", use_seps=True)

# Style group labels
.tab_style(
    style=[
        style.fill(color="#e8e8e8"),
        style.text(weight="bold")
    ],
    locations=loc.row_groups()
)

)

table.save("row_groups.html")

Column Spanners:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Product": ["Widget A", "Widget B", "Gadget X"], "Q1_Sales": [25000, 32000, 18000], "Q1_Units": [250, 320, 90], "Q2_Sales": [28000, 35000, 22000], "Q2_Units": [280, 350, 110], "Q3_Sales": [31000, 38000, 25000], "Q3_Units": [310, 380, 125] })

table = ( GT(df) .tab_header(title="Quarterly Performance")

# Create column spanners
.tab_spanner(
    label="Q1",
    columns=["Q1_Sales", "Q1_Units"]
)
.tab_spanner(
    label="Q2",
    columns=["Q2_Sales", "Q2_Units"]
)
.tab_spanner(
    label="Q3",
    columns=["Q3_Sales", "Q3_Units"]
)

# Rename columns
.cols_label(
    Q1_Sales="Sales",
    Q1_Units="Units",
    Q2_Sales="Sales",
    Q2_Units="Units",
    Q3_Sales="Sales",
    Q3_Units="Units"
)

# Format numbers
.fmt_currency(columns=["Q1_Sales", "Q2_Sales", "Q3_Sales"], currency="USD", decimals=0)
.fmt_integer(columns=["Q1_Units", "Q2_Units", "Q3_Units"], use_seps=True)

)

table.save("column_spanners.html")

Nested Groups:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Division": ["Consumer", "Consumer", "Consumer", "Enterprise", "Enterprise", "Enterprise"], "Category": ["Electronics", "Home", "Fashion", "Software", "Hardware", "Services"], "Product": ["Phones", "Furniture", "Apparel", "Cloud", "Servers", "Consulting"], "Revenue": [150, 45, 78, 220, 180, 95], "Growth": [0.12, 0.05, -0.02, 0.25, 0.08, 0.15] })

table = ( GT(df, groupname_col="Division", rowname_col="Category") .tab_header( title="Business Unit Performance", subtitle="Annual Revenue (Millions USD)" ) .fmt_currency(columns="Revenue", currency="USD", decimals=0) .fmt_percent(columns="Growth", decimals=1) )

table.save("nested_groups.html")

  1. Footnotes and Annotations

Adding Footnotes:

from great_tables import GT from great_tables import loc import pandas as pd

df = pd.DataFrame({ "Company": ["TechCorp", "DataInc", "CloudSoft", "AILabs"], "Revenue_B": [125.4, 98.2, 87.5, 76.3], "Employees": [45000, 28000, 15000, 8500], "Founded": [1985, 1998, 2010, 2015] })

table = ( GT(df) .tab_header( title="Tech Companies Overview", subtitle="Leading technology firms" )

# Add footnote to title
.tab_footnote(
    footnote="Revenue in billions USD",
    locations=loc.title()
)

# Add footnote to specific column
.tab_footnote(
    footnote="Full-time employees only",
    locations=loc.column_labels(columns="Employees")
)

# Add footnote to specific cell
.tab_footnote(
    footnote="Acquired by MegaCorp in 2024",
    locations=loc.body(columns="Company", rows=[2])
)

# Source note
.tab_source_note(
    source_note="Data as of December 2025"
)

.fmt_currency(columns="Revenue_B", currency="USD", decimals=1)
.fmt_integer(columns="Employees", use_seps=True)

)

table.save("footnotes.html")

Stubhead Labels:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Year": [2022, 2023, 2024, 2025], "Revenue": [85.2, 92.5, 105.8, 118.3], "Profit": [12.5, 15.8, 19.2, 23.1], "Margin": [0.147, 0.171, 0.181, 0.195] })

table = ( GT(df, rowname_col="Year") .tab_header(title="Financial Summary") .tab_stubhead(label="Fiscal Year") # Label for row names column

.fmt_currency(columns=["Revenue", "Profit"], currency="USD", decimals=1)
.fmt_percent(columns="Margin", decimals=1)

)

table.save("stubhead.html")

  1. Export Options

Export to HTML:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Item": ["A", "B", "C"], "Value": [100, 200, 150] })

table = GT(df).tab_header(title="Export Demo")

Save as HTML file

table.save("table.html")

Get HTML string

html_string = table.as_raw_html() print(html_string[:500]) # Preview

Export to Image (PNG):

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Product": ["Widget", "Gadget", "Tool"], "Price": [29.99, 49.99, 19.99], "Stock": [150, 85, 200] })

table = ( GT(df) .tab_header(title="Product Inventory") .fmt_currency(columns="Price", currency="USD") )

Save as PNG (requires webshot/chromedriver)

table.save("table.png")

Alternative: Use playwright

table.save("table.png", web_driver="playwright")

Inline Display in Notebooks:

from great_tables import GT import pandas as pd

df = pd.DataFrame({ "Name": ["Alice", "Bob", "Charlie"], "Score": [95, 87, 92] })

In Jupyter, just return the table object

table = GT(df).tab_header(title="Test Scores") table # Displays inline

Complete Examples

Example 1: Financial Report Table

from great_tables import GT, html from great_tables import style, loc import pandas as pd import numpy as np

def create_financial_report( data: pd.DataFrame, title: str = "Financial Report", output_path: str = "financial_report.html" ) -> GT: """ Create publication-quality financial report table.

Args:
    data: Financial data with columns for metrics and periods
    title: Report title
    output_path: Output HTML path

Returns:
    GT table object
"""

# Sample financial data
df = pd.DataFrame({
    "Metric": [
        "Revenue", "Cost of Sales", "Gross Profit",
        "Operating Expenses", "EBITDA", "Depreciation",
        "EBIT", "Interest Expense", "Pre-tax Income",
        "Taxes", "Net Income"
    ],
    "FY2023": [
        1250000, 625000, 625000,
        312500, 312500, 62500,
        250000, 25000, 225000,
        67500, 157500
    ],
    "FY2024": [
        1450000, 710500, 739500,
        348000, 391500, 72500,
        319000, 28000, 291000,
        87300, 203700
    ],
    "FY2025": [
        1680000, 806400, 873600,
        386400, 487200, 84000,
        403200, 30000, 373200,
        111960, 261240
    ],
    "Change_Pct": [
        15.9, 13.5, 18.1,
        11.0, 24.4, 15.9,
        26.4, 7.1, 28.3,
        28.3, 28.3
    ]
})

# Identify key rows
key_rows = [2, 4, 6, 10]  # Gross Profit, EBITDA, EBIT, Net Income

table = (
    GT(df)
    .tab_header(
        title=title,
        subtitle="Fiscal Year Comparison (USD)"
    )

    # Column labels
    .cols_label(
        Metric="",
        FY2023="FY 2023",
        FY2024="FY 2024",
        FY2025="FY 2025",
        Change_Pct="YoY Change"
    )

    # Format currencies
    .fmt_currency(
        columns=["FY2023", "FY2024", "FY2025"],
        currency="USD",
        decimals=0,
        use_seps=True
    )

    # Format percentage
    .fmt_percent(
        columns="Change_Pct",
        decimals=1,
        scale_values=False
    )

    # Style header
    .tab_style(
        style=[
            style.fill(color="#1a365d"),
            style.text(color="white", weight="bold")
        ],
        locations=loc.column_labels()
    )

    # Style key metric rows
    .tab_style(
        style=[
            style.fill(color="#f0f4f8"),
            style.text(weight="bold")
        ],
        locations=loc.body(rows=key_rows)
    )

    # Borders
    .tab_style(
        style=style.borders(sides="bottom", color="#1a365d", weight="2px"),
        locations=loc.column_labels()
    )
    .tab_style(
        style=style.borders(sides="top", color="#1a365d", weight="2px"),
        locations=loc.body(rows=[10])
    )

    # Positive/negative change colors
    .tab_style(
        style=style.text(color="#22543d"),
        locations=loc.body(
            columns="Change_Pct",
            rows=lambda x: x["Change_Pct"] > 0
        )
    )

    # Source note
    .tab_source_note(
        source_note="All figures in thousands USD. Change calculated FY2024 to FY2025."
    )

    # Options
    .tab_options(
        table_width="100%",
        table_font_size="14px"
    )
)

table.save(output_path)
print(f"Financial report saved to: {output_path}")

return table

Generate report

table = create_financial_report(df, "Annual Financial Report", "annual_report.html")

Example 2: Sales Dashboard Table

from great_tables import GT, html from great_tables import style, loc import pandas as pd import numpy as np

def create_sales_dashboard_table(output_path: str = "sales_dashboard.html") -> GT: """ Create sales dashboard table with KPIs and sparklines. """

# Sample data
np.random.seed(42)
df = pd.DataFrame({
    "Region": ["North America", "Europe", "Asia Pacific", "Latin America", "Middle East"],
    "Revenue": [4250000, 3180000, 2890000, 1520000, 890000],
    "Target": [4000000, 3500000, 2500000, 1800000, 1000000],
    "Units": [42500, 31800, 57800, 30400, 17800],
    "Customers": [1250, 980, 1560, 620, 340],
    "Growth": [0.12, -0.05, 0.28, 0.08, 0.15],
    "Satisfaction": [4.5, 4.2, 4.7, 4.1, 4.3]
})

# Calculate achievement
df["Achievement"] = df["Revenue"] / df["Target"]

def achievement_bar(pct):
    """Create progress bar for achievement."""
    width = min(pct * 100, 100)
    if pct >= 1.0:
        color = "#22c55e"  # Green
    elif pct >= 0.9:
        color = "#eab308"  # Yellow
    else:
        color = "#ef4444"  # Red

    return html(f'''
        &#x3C;div style="display: flex; align-items: center; gap: 8px;">
            &#x3C;div style="background: #e5e7eb; width: 60px; height: 12px; border-radius: 6px;">
                &#x3C;div style="background: {color}; width: {width}%; height: 100%; border-radius: 6px;">&#x3C;/div>
            &#x3C;/div>
            &#x3C;span style="font-size: 12px;">{pct*100:.0f}%&#x3C;/span>
        &#x3C;/div>
    ''')

def growth_indicator(value):
    """Create growth indicator with arrow."""
    if value > 0:
        arrow = "&#x26;#9650;"  # Up
        color = "#22c55e"
    elif value &#x3C; 0:
        arrow = "&#x26;#9660;"  # Down
        color = "#ef4444"
    else:
        arrow = "&#x26;#9654;"  # Right
        color = "#6b7280"

    return html(f'&#x3C;span style="color: {color};">{arrow} {abs(value)*100:.1f}%&#x3C;/span>')

def star_rating(score):
    """Create star rating display."""
    full_stars = int(score)
    half_star = score - full_stars >= 0.5
    empty_stars = 5 - full_stars - (1 if half_star else 0)

    stars = "&#x26;#9733;" * full_stars
    if half_star:
        stars += "&#x26;#9734;"
    stars += "&#x26;#9734;" * empty_stars

    return html(f'&#x3C;span style="color: #f59e0b;">{stars}&#x3C;/span> ({score:.1f})')

df["Achievement_Bar"] = df["Achievement"].apply(achievement_bar)
df["Growth_Display"] = df["Growth"].apply(growth_indicator)
df["Rating_Display"] = df["Satisfaction"].apply(star_rating)

table = (
    GT(df[["Region", "Revenue", "Achievement_Bar", "Units", "Customers", "Growth_Display", "Rating_Display"]])
    .tab_header(
        title="Regional Sales Performance",
        subtitle="Q4 2025 Dashboard"
    )

    .cols_label(
        Region="Region",
        Revenue="Revenue",
        Achievement_Bar="Target Achievement",
        Units="Units Sold",
        Customers="Active Customers",
        Growth_Display="YoY Growth",
        Rating_Display="CSAT Score"
    )

    # Format numbers
    .fmt_currency(columns="Revenue", currency="USD", decimals=0, use_seps=True)
    .fmt_integer(columns=["Units", "Customers"], use_seps=True)

    # Header style
    .tab_style(
        style=[
            style.fill(color="#0f172a"),
            style.text(color="white", weight="bold", size="13px")
        ],
        locations=loc.column_labels()
    )

    # Alternating rows
    .tab_style(
        style=style.fill(color="#f8fafc"),
        locations=loc.body(rows=[1, 3])
    )

    # Region column style
    .tab_style(
        style=style.text(weight="bold"),
        locations=loc.body(columns="Region")
    )

    .tab_source_note("Data refreshed: January 17, 2026")

    .tab_options(
        table_width="100%",
        data_row_padding="12px"
    )
)

table.save(output_path)
return table

table = create_sales_dashboard_table("sales_dashboard.html")

Example 3: Scientific Data Table

from great_tables import GT from great_tables import style, loc import pandas as pd import numpy as np

def create_scientific_table(output_path: str = "scientific_table.html") -> GT: """ Create publication-quality scientific data table. """

# Experimental results data
df = pd.DataFrame({
    "Treatment": ["Control", "Drug A (10mg)", "Drug A (50mg)", "Drug B (10mg)", "Drug B (50mg)"],
    "N": [25, 24, 26, 25, 23],
    "Mean": [45.2, 52.8, 61.3, 48.9, 58.7],
    "SD": [8.5, 9.2, 10.1, 8.9, 11.2],
    "SE": [1.7, 1.88, 1.98, 1.78, 2.34],
    "CI_Lower": [41.7, 48.9, 57.2, 45.2, 53.8],
    "CI_Upper": [48.7, 56.7, 65.4, 52.6, 63.6],
    "P_Value": [None, 0.042, 0.001, 0.185, 0.003]
})

def format_ci(row):
    """Format confidence interval."""
    return f"[{row['CI_Lower']:.1f}, {row['CI_Upper']:.1f}]"

df["95% CI"] = df.apply(format_ci, axis=1)

def format_pvalue(p):
    """Format p-value with significance markers."""
    if p is None:
        return "-"
    elif p &#x3C; 0.001:
        return "&#x3C;0.001***"
    elif p &#x3C; 0.01:
        return f"{p:.3f}**"
    elif p &#x3C; 0.05:
        return f"{p:.3f}*"
    else:
        return f"{p:.3f}"

df["P_Formatted"] = df["P_Value"].apply(format_pvalue)

table = (
    GT(df[["Treatment", "N", "Mean", "SD", "SE", "95% CI", "P_Formatted"]])
    .tab_header(
        title="Table 1. Treatment Effects on Primary Outcome",
        subtitle="Values represent endpoint measurements (units)"
    )

    .cols_label(
        Treatment="Treatment Group",
        N="n",
        Mean="Mean",
        SD="SD",
        SE="SE",
        P_Formatted="P-value"
    )

    # Format numbers
    .fmt_number(columns=["Mean", "SD", "SE"], decimals=1)

    # Center align numeric columns
    .cols_align(
        align="center",
        columns=["N", "Mean", "SD", "SE", "95% CI", "P_Formatted"]
    )

    # Header style (minimal, scientific)
    .tab_style(
        style=[
            style.text(weight="bold"),
            style.borders(sides="bottom", weight="2px", color="black")
        ],
        locations=loc.column_labels()
    )

    # Control row italic
    .tab_style(
        style=style.text(style="italic"),
        locations=loc.body(rows=[0], columns="Treatment")
    )

    # Significant p-values bold
    .tab_style(
        style=style.text(weight="bold"),
        locations=loc.body(rows=[1, 2, 4], columns="P_Formatted")
    )

    # Bottom border
    .tab_style(
        style=style.borders(sides="bottom", weight="2px", color="black"),
        locations=loc.body(rows=[-1])
    )

    # Footnotes
    .tab_footnote(
        footnote="Standard deviation",
        locations=loc.column_labels(columns="SD")
    )
    .tab_footnote(
        footnote="Standard error of the mean",
        locations=loc.column_labels(columns="SE")
    )

    .tab_source_note("*p&#x3C;0.05, **p&#x3C;0.01, ***p&#x3C;0.001 vs. Control (Dunnett's test)")
    .tab_source_note("CI = Confidence Interval")

    .tab_options(
        table_font_names="Times New Roman, serif",
        table_font_size="12px"
    )
)

table.save(output_path)
return table

table = create_scientific_table("experiment_results.html")

Integration Examples

Great Tables with Streamlit

import streamlit as st from great_tables import GT import pandas as pd

st.set_page_config(page_title="Table Demo", layout="wide") st.title("Great Tables in Streamlit")

Sample data

df = pd.DataFrame({ "Product": ["Widget A", "Widget B", "Gadget X"], "Price": [29.99, 49.99, 19.99], "Stock": [150, 85, 200], "Rating": [4.5, 4.2, 4.8] })

Create table

table = ( GT(df) .tab_header(title="Product Catalog") .fmt_currency(columns="Price", currency="USD") .fmt_number(columns="Rating", decimals=1) )

Display in Streamlit

st.html(table.as_raw_html())

Great Tables with Polars

from great_tables import GT import polars as pl

Create Polars DataFrame

df_polars = pl.DataFrame({ "name": ["Alice", "Bob", "Charlie"], "score": [95, 87, 92], "grade": ["A", "B+", "A-"] })

Convert to pandas for Great Tables

df_pandas = df_polars.to_pandas()

Create table

table = ( GT(df_pandas) .tab_header(title="Student Scores") .cols_label( name="Student", score="Score", grade="Grade" ) )

table.save("polars_table.html")

Best Practices

  1. Keep Tables Focused

GOOD: Select relevant columns

df_display = df[["Name", "Revenue", "Growth"]] table = GT(df_display)

AVOID: Displaying too many columns

table = GT(df) # If df has 20+ columns

  1. Use Appropriate Formatting

GOOD: Match format to data type

table = ( GT(df) .fmt_currency(columns="Price", currency="USD") .fmt_percent(columns="Growth", decimals=1) .fmt_integer(columns="Units", use_seps=True) )

AVOID: Generic number format for everything

  1. Limit Rows for Display

GOOD: Show summary or top N

df_top10 = df.nlargest(10, "Revenue") table = GT(df_top10)

AVOID: Displaying thousands of rows

  1. Use Color Sparingly

GOOD: Highlight key information

table.data_color( columns="Performance", palette=["#fee2e2", "#dcfce7"], # Subtle colors domain=[0, 100] )

AVOID: Rainbow color schemes

Troubleshooting

Common Issues

Issue: Table not displaying in Jupyter

Solution: Ensure rich display

from great_tables import GT table = GT(df) display(table) # Or just: table

Issue: HTML export looks different

Solution: Include all styling

table.save("output.html") # Includes CSS

Issue: Image export not working

Solution: Install webshot or use playwright

pip install webshot

or

pip install playwright playwright install chromium

table.save("output.png", web_driver="playwright")

Issue: Slow with large DataFrames

Solution: Limit rows

df_display = df.head(100) table = GT(df_display)

Issue: Special characters not rendering

Solution: Use html() helper

from great_tables import html cell_content = html("&euro; 100") # Euro symbol

Version History

  • 1.0.0 (2026-01-17): Initial release

  • Basic table creation and styling

  • Column formatting (currency, percent, date)

  • Conditional formatting and color scales

  • Row and column grouping

  • Footnotes and annotations

  • Export to HTML and images

  • Complete report examples

  • Integration with Streamlit and Polars

  • Best practices and troubleshooting

Resources

Create publication-quality tables with Great Tables - beautiful data presentation made easy!

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

echarts

No summary provided by upstream source.

Repository SourceNeeds Review
General

pandoc

No summary provided by upstream source.

Repository SourceNeeds Review
General

mkdocs

No summary provided by upstream source.

Repository SourceNeeds Review
General

gis

No summary provided by upstream source.

Repository SourceNeeds Review