# Mastering Plotly Express: Create Interactive Charts in Python URL: https://madhudadi.in/blog/posts/mastering-plotly-express-create-interactive-charts-in-python Published: 2026-06-12 Tags: python Read time: 55 min Difficulty: intermediate > 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.# 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.