#pythonIntermediate

Plotly Express: Create Interactive Charts in Python

Jun 12, 2026
55 min read

AI Insights

Powered by GPT-4o-mini

Verified Context: mastering-plotly-express-create-interactive-charts-in-python
Quick Answer

Learn Plotly Express with original datasets: interactive scatter plots, line charts, bars, histograms, pie and donut charts, sunburst, treemap, heatmaps, 3D charts, scatter matrix plots, facets, and subplots.

Quick Summary

Learn to create interactive charts with Plotly Express in Python. Explore scatter, line, bar, and more with practical examples.

Plotly Express: Interactive Scatter, Line, Bar, Histogram, Pie, Sunburst, Heatmaps, 3D Charts, Facets, and Subplots

Plotly helps you build interactive charts in Python.

Matplotlib is excellent when you want full control over static figures. Plotly is excellent when you want charts that users can hover, zoom, pan, filter, and inspect in a browser or notebook.

In this guide, you will learn Plotly Express through practical examples:

  • interactive scatter plots
  • color, size, hover labels, and tooltips
  • log-scaled axes
  • animated charts
  • line charts
  • single, grouped, and stacked bar charts
  • histograms
  • pie and donut charts
  • sunburst and treemap charts
  • heatmaps with px.imshow
  • 3D scatter plots
  • scatter matrix plots
  • facet grids
  • mixed dashboards with make_subplots

The examples use original synthetic datasets, not copied notebook, course, sports, or public tutorial data.

Files Used In This Guide

Use these CSV files:

  • plotly_country_metrics.csv
  • plotly_cafe_orders.csv

Place them in the same folder as your notebook or script.

If you keep them in a data/ folder, change the paths like this:

python
country = pd.read_csv("data/plotly_country_metrics.csv")
orders = pd.read_csv("data/plotly_cafe_orders.csv")

What You Will Learn

By the end, you should be able to:

  • create a Plotly Express figure from a Pandas DataFrame
  • decide when to use Plotly Express and when to use Graph Objects
  • add hover labels and custom tooltips
  • map columns to color, size, symbol, and animation
  • use log axes for values with large ranges
  • build grouped and stacked bar charts
  • create distribution charts with histograms
  • use pie charts only when they are appropriate
  • visualize hierarchy with sunburst and treemap charts
  • convert pivot tables into heatmaps
  • create 3D charts without manual JavaScript
  • split a chart into facets
  • combine multiple charts with make_subplots

1. Setup

Install Plotly if needed:

bash
pip install plotly pandas

Import the libraries:

python
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

Load the datasets:

python
country = pd.read_csv("plotly_country_metrics.csv")
orders = pd.read_csv("plotly_cafe_orders.csv")

orders["date"] = pd.to_datetime(orders["date"])

print(country.head())
print(orders.head())

The country table contains fictional country-level metrics across multiple years.

The orders table contains fictional cafe orders across cities, products, channels, and customer types.

2. Plotly Express vs Graph Objects

Plotly has two common APIs:

  • plotly.express for quick charts from tidy DataFrames
  • plotly.graph_objects for lower-level figure construction

Most beginner and intermediate work should start with Plotly Express.

Example with Graph Objects:

python
auralia = country[country["country"] == "Auralia"]

fig = go.Figure()

fig.add_trace(
    go.Scatter(
        x=auralia["year"],
        y=auralia["internet_users_pct"],
        mode="lines+markers",
        name="Auralia",
    )
)

fig.update_layout(
    title="Internet Adoption In Auralia",
    xaxis_title="Year",
    yaxis_title="Internet Users (%)",
)

fig.show()

The same chart with Plotly Express:

python
fig = px.line(
    auralia,
    x="year",
    y="internet_users_pct",
    markers=True,
    title="Internet Adoption In Auralia",
)

fig.show()

Use Plotly Express when your data is already in a DataFrame and you want a fast chart.

Use Graph Objects when you need precise control over traces, subplots, annotations, or custom dashboards.

3. First Interactive Scatter Plot

A scatter plot compares two numeric columns.

This chart compares life expectancy and GDP per person for the latest year:

python
latest = country[country["year"] == country["year"].max()]

fig = px.scatter(
    latest,
    x="life_expectancy",
    y="gdp_per_capita",
    title="Life Expectancy vs GDP Per Person",
)

fig.show()

Plotly charts are interactive by default.

You can hover over a point, zoom into a region, pan around the chart, and save the image from the chart toolbar.

4. Color, Size, And Hover Labels

Plotly Express becomes powerful when you map DataFrame columns to visual encodings.

Example:

  • x-axis: life expectancy
  • y-axis: GDP per person
  • color: continent
  • size: population
  • hover label: country
python
fig = px.scatter(
    latest,
    x="life_expectancy",
    y="gdp_per_capita",
    color="continent",
    size="population_millions",
    hover_name="country",
    title="Country Metrics With Color, Size, And Hover",
    labels={
        "life_expectancy": "Life Expectancy",
        "gdp_per_capita": "GDP Per Person",
        "population_millions": "Population (Millions)",
    },
)

fig.show()

Use hover_name for the main label users should see first.

Use labels to make axis names readable.

5. Custom Hover Data

By default, Plotly shows columns used in the chart.

Use hover_data when you want to add or hide details.

python
fig = px.scatter(
    latest,
    x="internet_users_pct",
    y="education_index",
    color="continent",
    size="population_millions",
    hover_name="country",
    hover_data={
        "population_millions": ":.1f",
        "gdp_per_capita": ":,.0f",
        "carbon_tons_per_person": ":.2f",
    },
    title="Education And Internet Access",
)

fig.show()

The format strings make tooltips easier to scan.

6. Log Axes

Use a log axis when values have a wide range.

GDP per person can vary a lot, so a log-scaled y-axis can make the pattern easier to read.

python
fig = px.scatter(
    latest,
    x="life_expectancy",
    y="gdp_per_capita",
    color="continent",
    size="population_millions",
    hover_name="country",
    log_y=True,
    title="Life Expectancy vs GDP Per Person On A Log Scale",
)

fig.show()

Do not use log scales silently. Make sure the chart title, axis, or surrounding explanation makes the scale clear.

7. Animated Scatter Plot

Animation helps when the same entities repeat across time.

python
fig = px.scatter(
    country,
    x="life_expectancy",
    y="gdp_per_capita",
    color="continent",
    size="population_millions",
    hover_name="country",
    animation_frame="year",
    animation_group="country",
    range_x=[65, 84],
    range_y=[12000, 62000],
    title="Country Development Metrics Over Time",
)

fig.show()

animation_group tells Plotly that the same country appears in multiple frames.

Fixed ranges prevent the chart from jumping as the animation moves between years.

8. Line Charts

Line charts are useful for trends.

python
fig = px.line(
    country,
    x="year",
    y="internet_users_pct",
    color="country",
    markers=True,
    title="Internet Adoption By Country",
)

fig.show()

If too many lines make the chart noisy, filter the data first:

python
focus_countries = ["Auralia", "Borevia", "Eldora", "Harboris"]
focus = country[country["country"].isin(focus_countries)]

fig = px.line(
    focus,
    x="year",
    y="life_expectancy",
    color="country",
    markers=True,
    title="Life Expectancy Trend For Selected Countries",
)

fig.show()

9. Bar Charts

A bar chart compares categories.

Create a continent-level summary:

python
continent_summary = (
    latest
    .groupby("continent", as_index=False)
    .agg(
        population_millions=("population_millions", "sum"),
        avg_gdp_per_capita=("gdp_per_capita", "mean"),
        avg_life_expectancy=("life_expectancy", "mean"),
    )
)

fig = px.bar(
    continent_summary,
    x="continent",
    y="population_millions",
    color="continent",
    text_auto=".1f",
    title="Population By Continent Group",
)

fig.show()

text_auto writes values on the bars.

Use it when the chart has enough space.

10. Grouped Bar Chart

Grouped bars compare multiple categories side by side.

python
city_category = (
    orders
    .groupby(["city", "category"], as_index=False)
    .agg(revenue=("total_bill", "sum"))
)

fig = px.bar(
    city_category,
    x="city",
    y="revenue",
    color="category",
    barmode="group",
    text_auto=".0f",
    title="Cafe Revenue By City And Category",
)

fig.show()

Grouped bars work well when each x-axis category has a small number of groups.

11. Stacked Bar Chart

Stacked bars show composition.

python
city_channel = (
    orders
    .groupby(["city", "channel"], as_index=False)
    .agg(revenue=("total_bill", "sum"))
)

fig = px.bar(
    city_channel,
    x="city",
    y="revenue",
    color="channel",
    title="Revenue Composition By Sales Channel",
)

fig.show()

The default px.bar behavior stacks bars when multiple rows share the same x-axis category.

Use stacked bars for part-to-whole comparison.

Use grouped bars for exact side-by-side comparison.

12. Log-Scaled Bar Chart

If one category is much larger than the others, a log axis can help.

python
product_revenue = (
    orders
    .groupby("product", as_index=False)
    .agg(revenue=("total_bill", "sum"))
    .sort_values("revenue", ascending=False)
)

fig = px.bar(
    product_revenue,
    x="product",
    y="revenue",
    log_y=True,
    text_auto=".0f",
    title="Product Revenue On A Log Scale",
)

fig.update_layout(xaxis_tickangle=-35)
fig.show()

Rotate long labels when they crowd the x-axis.

13. Histograms

Histograms show distributions.

python
fig = px.histogram(
    orders,
    x="total_bill",
    nbins=14,
    color="channel",
    marginal="box",
    title="Distribution Of Order Values",
)

fig.show()

marginal="box" adds a compact box plot above the histogram.

Other useful marginal options include:

python
"rug"
"violin"
"box"

14. Histogram With Facets

Facets split one chart into small multiples.

python
fig = px.histogram(
    orders,
    x="service_rating",
    color="customer_type",
    facet_col="channel",
    nbins=10,
    title="Service Ratings By Channel",
)

fig.show()

Facets are often better than putting too many colors into one chart.

15. Pie And Donut Charts

Pie charts are useful only for simple part-to-whole comparisons.

Use them when:

  • there are few categories
  • the values add up to a meaningful whole
  • exact comparison is not the main goal
python
category_share = (
    orders
    .groupby("category", as_index=False)
    .agg(revenue=("total_bill", "sum"))
)

fig = px.pie(
    category_share,
    values="revenue",
    names="category",
    title="Revenue Share By Category",
)

fig.show()

A donut chart is a pie chart with a hole:

python
fig = px.pie(
    category_share,
    values="revenue",
    names="category",
    hole=0.45,
    title="Revenue Share By Category",
)

fig.show()

If you need accurate category comparison, prefer a bar chart.

16. Sunburst Charts

Sunburst charts show hierarchy.

This example shows revenue from city to category to product:

python
order_hierarchy = (
    orders
    .groupby(["city", "category", "product"], as_index=False)
    .agg(
        revenue=("total_bill", "sum"),
        avg_rating=("service_rating", "mean"),
    )
)

fig = px.sunburst(
    order_hierarchy,
    path=["city", "category", "product"],
    values="revenue",
    color="avg_rating",
    color_continuous_scale="Blues",
    title="Cafe Revenue Hierarchy",
)

fig.show()

Sunburst charts are useful when hierarchy matters more than exact bar-to-bar comparison.

17. Treemap Charts

A treemap uses rectangles instead of radial slices.

python
fig = px.treemap(
    order_hierarchy,
    path=["city", "category", "product"],
    values="revenue",
    color="avg_rating",
    color_continuous_scale="Greens",
    title="Cafe Revenue Treemap",
)

fig.show()

Treemaps often use screen space more efficiently than sunburst charts.

18. Heatmaps With px.imshow

Heatmaps are useful for matrix-shaped summaries.

Create a pivot table:

python
rating_matrix = orders.pivot_table(
    index="city",
    columns="category",
    values="service_rating",
    aggfunc="mean",
)

fig = px.imshow(
    rating_matrix,
    text_auto=".2f",
    color_continuous_scale="Blues",
    title="Average Service Rating By City And Category",
)

fig.show()

The input to px.imshow can be a NumPy array, a list of lists, or a Pandas DataFrame.

A DataFrame is convenient because it keeps row and column labels.

19. Another Heatmap: Fulfillment Time

python
time_matrix = orders.pivot_table(
    index="city",
    columns="channel",
    values="delivery_minutes",
    aggfunc="mean",
)

fig = px.imshow(
    time_matrix,
    text_auto=".1f",
    color_continuous_scale="Oranges",
    title="Average Fulfillment Minutes By City And Channel",
)

fig.show()

Use heatmaps when the same metric is measured across two category axes.

20. 3D Scatter Plot

3D charts can be helpful for exploration, but they are not always the best presentation choice.

Use them when rotation helps users inspect the data.

python
fig = px.scatter_3d(
    latest,
    x="internet_users_pct",
    y="education_index",
    z="gdp_per_capita",
    color="continent",
    size="population_millions",
    hover_name="country",
    title="3D Country Metrics",
)

fig.show()

Do not use 3D just because it looks impressive.

For reports, a 2D scatter plot is often easier to read.

21. Scatter Matrix

A scatter matrix compares multiple numeric columns pairwise.

python
fig = px.scatter_matrix(
    latest,
    dimensions=[
        "life_expectancy",
        "gdp_per_capita",
        "internet_users_pct",
        "education_index",
    ],
    color="continent",
    hover_name="country",
    title="Scatter Matrix For Country Metrics",
)

fig.update_traces(diagonal_visible=False)
fig.show()

Use a scatter matrix for quick relationship scanning.

It can become crowded if you include too many columns.

22. Facet Columns

Facets create one small chart per category.

python
fig = px.scatter(
    country,
    x="life_expectancy",
    y="gdp_per_capita",
    color="continent",
    hover_name="country",
    facet_col="year",
    facet_col_wrap=3,
    title="Life Expectancy vs GDP Across Years",
)

fig.show()

facet_col_wrap=3 places three facet panels per row.

23. Facet Rows And Columns

You can facet by two category variables at once.

python
fig = px.scatter(
    orders,
    x="total_bill",
    y="tip",
    color="customer_type",
    facet_col="channel",
    facet_row="city",
    hover_name="product",
    title="Tips vs Order Value By City And Channel",
)

fig.show()

This can produce many panels.

Use it only when the grid remains readable.

24. Updating Layout

Every Plotly Express chart returns a Figure object.

You can update that object before showing it.

python
fig = px.scatter(
    latest,
    x="internet_users_pct",
    y="life_expectancy",
    color="continent",
    hover_name="country",
    title="Internet Access And Life Expectancy",
)

fig.update_layout(
    template="plotly_white",
    legend_title_text="Continent Group",
    title_x=0.02,
)

fig.update_xaxes(title="Internet Users (%)")
fig.update_yaxes(title="Life Expectancy")

fig.show()

Common layout changes:

python
fig.update_layout(template="plotly_white")
fig.update_layout(height=550, width=900)
fig.update_layout(legend_title_text="Group")
fig.update_xaxes(tickangle=-30)

25. Saving Interactive Charts

Save an interactive chart as HTML:

python
fig.write_html("country_scatter.html")

This creates a file that can be opened in a browser.

Save a static image only if you installed the static export dependency:

bash
pip install kaleido

Then:

python
fig.write_image("country_scatter.png")

Use HTML when interactivity matters.

Use PNG or SVG for static reports, slide decks, and documents.

26. Subplots With make_subplots

Plotly Express is convenient, but mixed dashboards often use Graph Objects.

Create summaries:

python
monthly_revenue = (
    orders
    .assign(month=orders["date"].dt.to_period("M").astype(str))
    .groupby("month", as_index=False)
    .agg(revenue=("total_bill", "sum"))
)

rating_by_city = (
    orders
    .groupby("city", as_index=False)
    .agg(avg_rating=("service_rating", "mean"))
)

Build a 2x2 dashboard:

python
fig = make_subplots(
    rows=2,
    cols=2,
    subplot_titles=[
        "Monthly Revenue",
        "Average Rating By City",
        "Order Value Distribution",
        "Internet Adoption Trend",
    ],
)

fig.add_trace(
    go.Scatter(
        x=monthly_revenue["month"],
        y=monthly_revenue["revenue"],
        mode="lines+markers",
        name="Revenue",
    ),
    row=1,
    col=1,
)

fig.add_trace(
    go.Bar(
        x=rating_by_city["city"],
        y=rating_by_city["avg_rating"],
        name="Rating",
    ),
    row=1,
    col=2,
)

fig.add_trace(
    go.Histogram(
        x=orders["total_bill"],
        name="Order Values",
    ),
    row=2,
    col=1,
)

for country_name in ["Auralia", "Eldora", "Harboris"]:
    temp = country[country["country"] == country_name]
    fig.add_trace(
        go.Scatter(
            x=temp["year"],
            y=temp["internet_users_pct"],
            mode="lines+markers",
            name=country_name,
        ),
        row=2,
        col=2,
    )

fig.update_layout(
    title="Cafe And Country Metrics Dashboard",
    height=750,
    showlegend=True,
)

fig.show()

This pattern is useful when one dashboard needs different chart types.

27. Practice Problems

Use the two CSV files to solve these problems.

Problem 1: Best GDP Scatter Plot

Create a scatter plot with:

  • x-axis: life_expectancy
  • y-axis: gdp_per_capita
  • color: continent
  • size: population_millions
  • hover label: country
  • only the latest year

Add a clear title and readable axis labels.

Problem 2: Animated Internet Adoption

Create an animated scatter plot with:

  • x-axis: internet_users_pct
  • y-axis: education_index
  • animation by year
  • animation group by country
  • color by continent

Use fixed x and y ranges.

Problem 3: Cafe Revenue Bars

Create a grouped bar chart showing revenue by:

  • x-axis: city
  • y-axis: total total_bill
  • color: category

Use text_auto.

Problem 4: Channel Composition

Create a stacked bar chart showing revenue by:

  • x-axis: city
  • color: channel

Explain which city has the strongest delivery contribution.

Problem 5: Order Value Histogram

Create a histogram of total_bill.

Add:

  • color="customer_type"
  • nbins=12
  • marginal="box"

Problem 6: Category Donut Chart

Create a donut chart showing revenue share by product category.

Then create a bar chart with the same data and compare which chart is easier to read.

Problem 7: Sunburst Hierarchy

Create a sunburst chart with:

  • city
  • category
  • product

Use revenue as the value and average rating as the color.

Problem 8: Heatmap From A Pivot Table

Create a pivot table where:

  • rows are city
  • columns are channel
  • values are average delivery_minutes

Display it with px.imshow.

Problem 9: 3D Country Metrics

Create a 3D scatter plot with:

  • x-axis: internet_users_pct
  • y-axis: education_index
  • z-axis: gdp_per_capita
  • color: continent
  • size: population_millions

Write one sentence explaining whether the 3D version adds insight.

Problem 10: Faceted Tips Chart

Create a faceted scatter plot using orders:

  • x-axis: total_bill
  • y-axis: tip
  • color: customer_type
  • facet column: channel

Then add facet_row="city" and decide whether the result is too dense.

28. Plotly Express Checklist

Use this checklist when building Plotly charts:

  • Is the data in a tidy DataFrame?
  • Does each axis have a clear label?
  • Does color encode a real variable?
  • Is the hover information helpful but not noisy?
  • Would a log scale make the pattern clearer?
  • Are there too many categories for one chart?
  • Would facets make the comparison easier?
  • Is a pie chart really better than a bar chart?
  • Does a 3D chart add insight, or only visual complexity?
  • Should the output be saved as HTML for interactivity?

29. Key Takeaways

Plotly Express lets you build interactive charts quickly from Pandas DataFrames.

Start with px.scatter, px.line, px.bar, and px.histogram.

Then add color, size, hover labels, facets, animation, and layout updates.

Use hierarchy charts, heatmaps, 3D charts, and subplots when the data actually needs them.

The goal is not to use every Plotly feature.

The goal is to make data easier to explore and explain.

Frequently Asked Questions

What types of charts can you create with Plotly Express?
You can create interactive scatter, line, bar, histogram, pie, sunburst, heatmaps, 3D charts, facets, and subplots with Plotly Express.
When should you use Plotly Express over Matplotlib?
Plotly Express is excellent when you want charts that users can hover, zoom, pan, filter, and inspect in a browser or notebook, whereas Matplotlib is better for full control over static figures.
What datasets are used in the guide for creating charts?
The guide uses synthetic datasets from the CSV files 'plotlycountrymetrics.csv' and 'plotlycafeorders.csv'.
What are some features you can add to Plotly Express charts?
You can add hover labels, custom tooltips, map columns to color, size, symbol, and animation, and use log axes for values with large ranges.
How do you install Plotly and Pandas for this guide?
You can install Plotly and Pandas using the command 'pip install plotly pandas'.

Related Work

See how this thinking shows up in shipped systems.