Featured resource
Tech Upskilling Playbook 2025
Tech Upskilling Playbook

Build future-ready tech teams and hit key business milestones with seven proven plays from industry leaders.

Learn more
  • Labs icon Lab
  • Data
Labs

Build a Scatter Plot in Python to Visualize Relationships between Discounts and Revenue

In this Code Lab, learners will build advanced scatter plots in Python using Plotly Express to analyze relationships between discounts and revenue. Starting with simple plots, they will progressively customize markers, encode multiple variables, add trendlines, apply faceting, and prepare highly interactive business-ready visualizations. This hands-on project mirrors real-world business analysis performed by sales and business intelligence teams.

Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 48m
Last updated
Clock icon Jul 16, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Getting Started

    Welcome to this interactive Code Lab, where you’ll learn how to visualize data using scatter plots in Python with Plotly Express.

    You’ll begin by creating a basic scatter plot—then progressively enhance it with features like color, size, opacity, grouping, trendlines, and more. By the end of the lab, you’ll have a fully styled visualization that highlights the relationship between discounts and revenue.

    Each step introduces a specific concept and walks you through its implementation in a Jupyter Notebook environment.

    Open the Notebook

    From the workspace panel, open the notebook file: 1-step-one.ipynb.

    How to Complete Tasks

    Each task in the lab matches a pre-written code cell labeled Task 1.1, Task 1.2, and so on.

    To complete a task:

    • Locate the corresponding code cell in the notebook
    • Follow the # TODO comments provided in the cell
    • Run the cell using the Run button or press Shift + Enter
    • Save your work using the Save icon or File > Save and Checkpoint
    • Validate your solution by clicking Validate in the task block

    You do not need to open a terminal, create files, or use plt.savefig(). All code runs and renders inline in the notebook.


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

  2. Challenge

    Step 1: Creating Your First Scatter Plot

    Step 1: Build Your First Scatter Plot

    Scatter plots are one of the most effective ways to explore relationships between two numeric variables. Each point represents a single record in your dataset — positioned according to its x and y values.

    In this lab, you’ll examine how discount percentages influence revenue. By visualizing each sale as a point, you can begin to spot patterns like diminishing returns, pricing sweet spots, or possible outliers.

    To do this, you’ll use Plotly Express — a high-level API for creating interactive charts with minimal code. Its scatter() function automatically enables tooltips, zoom controls, and smooth interactivity — ideal for business analysis and dashboards.

    This step sets the foundation for more advanced customizations coming later. Your goal here is to get points on the page and make sure they’re labeled clearly.



    What You’ll Learn in This Step

    • Create a scatter plot using px.scatter()
    • Plot DiscountPercent against Revenue
    • Add a title and rename axis labels for clarity


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Create a Basic Scatter Plot

    A scatter plot displays relationships between two numeric variables. Each data point is plotted on an x-y grid based on its values. These plots are ideal for identifying correlations, clusters, or outliers.

    In this case, each point represents a single sales transaction. You’ll plot:

    • DiscountPercent on the x-axis (how much discount was given)
    • Revenue on the y-axis (how much revenue that transaction generated)

    You’ll use Plotly Express, a concise interface for creating interactive charts. The function px.scatter() takes just a few core arguments:

    px.scatter(data_frame=df, x="DiscountPercent", y="Revenue")
    

    This creates a responsive chart with hover labels, zoom, and toolbars built in — perfect for exploring business data visually.

    Once you’ve created this basic plot, you’ll build on it with labels, grouping, and more styling in later steps.

    
    Adding a title and custom axis labels helps your chart communicate more clearly — especially when you're sharing results with others.
    
    Plotly Express allows you to do this directly within the `scatter()` function:
    
    - Use the `title` argument to display a headline above your chart.
    - Use the `labels` argument to rename columns on the x and y axes. This argument takes a dictionary, where each key is a column name and each value is the label you want to show.
    
    These updates don’t change the data — they simply improve the chart’s readability.
    
  3. Challenge

    Step 2: Customize Basic Marker Aesthetics

    Step 2: Customize Marker Aesthetics

    Now that you’ve created a working scatter plot, it’s time to style it for clarity and impact.

    Visual customizations help readers interpret your data more quickly. In this step, you’ll make changes that improve how the chart looks — without altering the actual values.

    To apply uniform styling across all data points, you'll use Plotly's update_traces() method. This allows you to customize markers after the chart is created.

    In this step, you will:

    • Apply a fixed color to all points
    • Set a consistent marker size
    • Add opacity to improve readability

    These small but powerful aesthetic tweaks are the foundation for more advanced styling later in the lab.



    What You’ll Learn in This Step

    • Use update_traces() to apply a fixed marker color
    • Set a uniform size for all markers
    • Improve readability by adjusting marker opacity


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Set a Fixed Marker Color

    Color helps your chart communicate — fast. Even without changing the data, you can guide the viewer’s focus using color design.

    To apply a single color to all points in a Plotly Express scatter plot, first create the plot using px.scatter(), then use the update_traces() method to set the marker color.

    This gives you full control over visual styling without relying on grouping or data columns.

    Examples of valid colors:

    • A named CSS color like "blue" or "darkorange"
    • A hex code like "#FF5733" for brand or theme consistency

    Using a consistent color improves clarity and gives your charts a polished look — especially before you introduce groupings later in the lab.

    Adjust Marker Size

    Marker size can affect how readable — or distracting — your scatter plot becomes.

    In Plotly Express, marker sizing is typically dynamic — tied to a column. But when you want every point to be the same size, you should apply a fixed numeric value using update_traces().

    You’ll still create the chart using px.scatter(), but then use:

    fig.update_traces(marker=dict(size=10))
    

    This ensures a uniform look and avoids errors caused by treating a number like a column name.

    You'll explore overlap and clarity in the next task — for now, focus on controlling the visual weight of each point using size. ### Apply Marker Opacity

    When points in a scatter plot start overlapping, it becomes harder to see patterns - especially in dense regions of the chart.

    Opacity helps solve that. The opacity property controls transparency and accepts a value between 0 (fully transparent) and 1 (fully solid). A value like 0.6 adds subtle transparency, revealing overlapping clusters and making the chart easier to read.

    To apply fixed opacity (alongside fixed color and size), use update_traces() after creating your figure:

    fig.update_traces(marker=dict(color="orange", size=10, opacity=0.6))
    

    This technique gives you full control over marker styling — perfect for fine-tuning readability before adding interactive features.

  4. Challenge

    Step 3: Encode Data Using Markers

    Step 3: Encode Data Using Marker Attributes

    Your chart doesn’t just have to show one variable at a time. In this step, you’ll learn how to map multiple data columns to different visual features of each marker.

    This process — called visual encoding — lets you reveal deeper patterns by adding more meaning to each point. Plotly Express makes this easy by allowing you to link dataset columns to attributes like:

    • color for categorical groups
    • size for quantitative scaling
    • symbol for shape-based distinction

    These techniques are often used in dashboards to layer more insight into a single chart without adding clutter.



    What You’ll Learn in This Step

    • Use the color argument to map a categorical column
    • Use size to encode quantitative magnitude
    • Use symbol to visually differentiate product types


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Color Markers by Category

    In previous steps, you applied a single color to all markers. Now it’s time to unlock categorical color encoding.

    Instead of passing a string to color, you’ll pass a column name — like "ProductCategory". Plotly will then assign a different color to each unique value in that column.

    This is useful when you want to:

    • Show how different groups behave across the same chart
    • Instantly compare clusters, trends, or anomalies

    Plotly automatically assigns a color palette, adds a legend, and updates hover info based on the values in that column.

    This is your first step toward multi-dimensional plotting — without adding any complexity to your data.

    Scale Marker Size by Revenue

    Color is great for categories — but what if you want to show quantity?

    With Plotly Express, you can map marker size to a numeric column like "Revenue". This lets you visually encode magnitude — larger values create larger points.

    This is especially helpful for:

    • Highlighting outliers with very high or low revenue
    • Showing which categories contribute most to sales
    • Surfacing patterns in value density

    When you assign size='Revenue', each point automatically scales to reflect that row’s value. It’s an intuitive way to communicate numerical weight across your dataset.

    Use Marker Symbols for Extra Grouping

    You’ve already used color and size to make your chart more expressive — now you’ll add marker symbols to represent categories visually.

    When you set symbol='ProductCategory', Plotly assigns a unique shape (circle, square, triangle, etc.) to each value in that column. This helps:

    • Differentiate groups even for users who can’t rely on color (e.g., colorblind viewers)
    • Make charts more readable when printed in black-and-white
    • Add another visual dimension without overwhelming the viewer

    Together with color and size, symbol encoding helps you deliver deeper insight using simple, elegant visuals.

  5. Challenge

    Step 4: Faceting and Category Ordering

    Step 4: Faceting and Category Ordering

    In this step, you’ll learn how to split your chart into multiple subplots using faceting. Faceting is a powerful way to compare different groups of your data in a grid of smaller charts, allowing for easy visual analysis.

    Faceting

    Faceting divides your plot into multiple smaller plots, each representing a different subset of your data. This is useful when you want to compare trends across categories, like analyzing ProductCategory across different subplots.

    Category Ordering

    By default, Plotly orders facets alphabetically. In this step, you’ll also learn how to control the order in which categories are displayed, using the category_orders argument. This helps in showing categories in a logical order, not just alphabetically.

    Manual Axis Range Control

    Finally, you’ll gain control over axis ranges. By manually adjusting the ranges, you can zoom in on specific data points for more focused analysis, such as narrowing down the DiscountPercent or Revenue.



    What You’ll Learn in This Step

    • Faceting: Split charts by categories like ProductCategory for clearer comparisons.
    • Category Ordering: Control the order of categories in facets.
    • Manual Axis Ranges: Adjust axis ranges to zoom in on specific data points.


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Apply Faceting to Split Charts by Product Category

    Faceting allows you to split a single chart into multiple subplots, each representing a subset of your data. This is useful when you want to compare trends across different categories within the same visualization.

    To facet your chart, you’ll use the facet_col argument in Plotly Express. The argument will take the name of the column you want to split by (in this case, ProductCategory). Plotly will then generate one subplot for each unique value in that column, showing you how the data behaves in different categories.

    Faceting benefits:

    • Compare subgroups: Quickly see how DiscountPercent and Revenue behave in different product categories (e.g., "Electronics", "Clothing").
    • Side-by-side analysis: Analyze trends across categories simultaneously for easy visual comparison.

    Faceting is one of the most effective ways to break down a large dataset and understand how it behaves across distinct groups. After this task, you’ll be able to create clearer, more digestible visualizations of grouped data.

    Apply Category Ordering to Control Facet Sequence

    By default, when you use faceting, Plotly will order the subplots alphabetically. However, there are times when you might want to control the sequence of facets to make them more meaningful. For example, it might make more sense to display “Electronics” before “Beauty”, or arrange the categories based on their natural order or importance.

    To control the order of categories, you can use the category_orders argument. This argument allows you to pass a dictionary, where the key is the column name (e.g., ProductCategory), and the value is a list of the category names in the desired order.

    For example, if you want to control the order of product types, you would specify it like this:

    category_orders = {'ProductCategory': ['Electronics', 'Beauty', 'Sports']}
    

    By doing this, you can control how the facets are displayed, ensuring the most logical or important sequence is followed. ### Manually Control Axis Ranges for Focus

    Sometimes, a large dataset can hide important trends if you're viewing too much of the data at once. Manually controlling the axis ranges lets you zoom in on specific regions of your data, making the chart more focused and easier to analyze.

    Plotly provides the update_xaxes() and update_yaxes() methods to manually set the range of the axes. The range is specified as a list with two values, like [0, 50], where the first value is the minimum and the second is the maximum.

    For example, if you want to focus on a smaller section of the DiscountPercent and Revenue axes, you can do something like this:

    fig.update_xaxes(range=[0, 50])
    fig.update_yaxes(range=[0, 2000])
    

    This allows you to zoom in on the most relevant data, making it easier to spot trends, outliers, or specific areas of interest.

    Why use axis ranges?

    • Zoom into trends: Focus on a part of the data where the action is happening.
    • Highlight data regions: Emphasize a specific range of values for better storytelling.
    • Improve readability: Remove irrelevant parts of the data that might clutter the visualization.
  6. Challenge

    Step 5: Add Trendline Analytics

    Step 5: Add Trendline Analytics

    Scatter plots are great for identifying patterns — but sometimes the pattern isn’t obvious until you overlay a trendline.

    In this step, you’ll add regression trendlines using Plotly Express. A trendline helps quantify the relationship between variables — especially when there’s noise in the data.

    Plotly supports several types of trendlines, and the most common for linear analysis is "ols" — short for Ordinary Least Squares regression.

    You’ll use trendlines to:

    • Show overall trends across all sales
    • Compare trends within each product category
    • Customize line colors to make trendlines more visually distinct

    These small additions turn your scatter plot from exploratory to analytical — and make it easier to spot relationships at a glance.



    What You’ll Learn in This Step

    • Add an OLS trendline to show overall correlation
    • Split trendlines by ProductCategory to analyze group trends
    • Customize trendline colors for better visibility and contrast


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Add a Basic OLS Trendline

    Scatter plots are useful for spotting patterns — but sometimes the signal gets buried in the noise. That’s where a trendline helps.

    In Plotly Express, the trendline argument allows you to overlay a statistical model onto your scatter plot. One of the most common models is "ols", which stands for Ordinary Least Squares regression — a linear model that estimates the best-fit line through the points.

    When you include trendline="ols" inside px.scatter(), Plotly:

    • Computes the regression based on your x and y values
    • Draws a line summarizing the linear relationship
    • Adds a separate legend entry and hover labels for the trendline

    You’re not modifying the dataset — just adding statistical context to the plot.

    This is especially helpful when you want to:

    • Reveal a correlation between variables
    • Emphasize an upward or downward trend
    • Simplify noisy data into a clearer signal

    The trendline overlays automatically unless filtered or grouped — and you’ll explore grouping in the next task.

    Group Trendlines by Product Category

    A single trendline shows the general trend across all data — but what if each product category behaves differently?

    By grouping your data using the color argument in Plotly Express, you can automatically fit separate trendlines for each category. This works seamlessly with trendline="ols".

    When color="ProductType" is added:

    • Plotly splits the data by category
    • It fits an individual regression line for each group
    • Each trendline gets its own color and legend entry

    This technique helps answer questions like:

    • Do discounts work better in some categories than others?
    • Are any categories showing a negative correlation?
    • Which group has the strongest revenue response?

    By the end of this task, your scatter plot will carry even more meaning — one trendline per group.

    Override Trendline Colors for Better Contrast

    Grouping trendlines by category adds insight — but sometimes the default colors make it hard to tell them apart.

    Plotly uses an automatic color scale, but you can override it using the color_discrete_map argument. This lets you assign specific colors to each category — useful when you need:

    • Better visual contrast
    • Color accessibility adjustments
    • Brand-compliant palettes

    color_discrete_map takes a dictionary:

    color_discrete_map = {
        "Clothing": "orange",
        "Electronics": "green",
        "Furniture": "blue"
    }
    

    When passed into px.scatter(), this map overrides the defaults — ensuring your plot is both informative and visually clear.

    This task isn’t about finding the “perfect palette” — it’s about learning how to take control of your visuals when the defaults fall short.

  7. Challenge

    Step 6: Advanced Marker and Hover Control

    Step 6: Advanced Marker and Hover Control

    As your scatter plot becomes more insightful, it’s time to improve how users interact with it.

    In this step, you’ll customize tooltips and marker styling — two features that enhance chart readability and user experience.

    Plotly’s hover controls let you decide:

    • Which fields appear in the tooltip
    • How those values are formatted
    • What style borders each marker should have

    These upgrades don’t just improve aesthetics — they improve communication. A clean tooltip and styled marker can help stakeholders read charts faster and trust what they see.



    What You’ll Learn in This Step

    • Use the hover_data argument to add custom fields
    • Format tooltip text with hovertemplate
    • Style marker outlines using marker=dict(...)


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Add Extra Fields to Hover Data

    Tooltips help users explore individual points on your scatter plot. By default, Plotly shows the x and y values — but you can add more context by including extra fields.

    Use the hover_data argument to specify additional columns you want to appear in the tooltip. You can pass:

    • A list of column names to include
    • A dictionary to include/exclude or control visibility

    For example:

    hover_data=["ProductCategory", "UnitsSold"]
    

    This will add both ProductCategory and UnitsSold to the tooltip.

    This makes your chart more informative without adding clutter — especially when key dimensions aren’t already encoded in color, size, or symbol. ### Customize Hovertemplate for Formatted Tooltips

    While hover_data adds fields to your tooltip, hovertemplate gives you full control over how that text appears.

    This is especially useful when:

    • You want to show fewer decimal places
    • You want consistent labeling
    • You want to eliminate extra text or rearrange the layout

    The hovertemplate is a string with placeholders, like:

    hovertemplate="Discount: %{x}%<br>Revenue: $%{y}<extra></extra>"
    
    • %{x} and %{y} refer to your axis values
    • <br> adds a line break
    • <extra></extra> removes the legend entry from the tooltip

    This formatting makes tooltips easier to read — and more polished for dashboards or executive reviews. ### Apply Marker Border Colors and Widths

    Marker borders can add clarity — especially when data points overlap or when your color palette is light.

    Plotly allows you to customize marker outlines using the marker dictionary inside update_traces() or directly within px.scatter().

    To style marker borders, set:

    • line_color for the outline color
    • line_width for the border thickness

    Example:

    fig.update_traces(marker=dict(line=dict(color="black", width=1)))
    

    This adds a 1-pixel black border to every point, improving contrast and definition.

    It’s a small touch, but in crowded plots or dashboards with strict color rules, it helps your data stand out cleanly. ### Style the Tooltip Appearance

    In addition to formatting tooltip content, Plotly lets you change the visual appearance of the tooltip box itself.

    This includes styling options such as:

    • Background color (bgcolor)
    • Border color (bordercolor)
    • Font size or color (optional)

    These visual tweaks improve readability and help your chart match branding or dark/light themes.

    To apply a custom style to all tooltips, use fig.update_traces() with the hoverlabel dictionary:

    fig.update_traces(hoverlabel=dict(bgcolor="white", bordercolor="black"))
    

    These changes apply globally to all hover boxes and don’t affect the data shown — only how the boxlooks.

  8. Challenge

    Step 7: Logarithmic Scaling and Error Bars

    Step 7: Logarithmic Scaling and Error Bars

    In this step, you’ll learn how to prepare your scatter plot for advanced business analysis — including log-based axes and visualizing uncertainty.

    These features are critical when:

    • Revenue spans multiple orders of magnitude
    • You want to highlight reliability or volatility in your data

    Plotly gives you direct support for:

    • Log scaling on any axis
    • Error bars to show variation or measurement confidence

    While these aren’t always needed for every dashboard, they’re essential for real-world analysis in finance, science, and operations.



    What You’ll Learn in This Step

    • Apply log_x or log_y to scale axes logarithmically
    • Use error_y to show confidence or variability in Revenue


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Apply Log Scaling to X or Y Axis

    In some datasets, numeric values span a huge range — from small to massive. Using a standard linear scale can compress smaller values and exaggerate large ones, hiding patterns.

    Logarithmic scaling solves this by transforming the axis to reflect the order of magnitude rather than fixed intervals.

    Plotly supports log scaling directly in px.scatter() using these arguments:

    • log_x=True for a log-scaled x-axis
    • log_y=True for a log-scaled y-axis

    This is especially useful when:

    • A few extreme values dominate the scale
    • You want to compare percentages or ratios
    • You’re analyzing exponential trends (e.g., ROI or decay)

    With log scaling, your plot becomes more balanced and patterns across multiple scales become clearer.

    Add Error Bars to Represent Revenue Uncertainty

    Charts usually show single values — but in many business scenarios, those values come with uncertainty.

    That’s where error bars come in.

    Error bars visually communicate:

    • Measurement uncertainty in data collection
    • Estimation ranges or forecast margins
    • Variation across repeated observations

    In Plotly, use the error_y argument to show vertical error bars:

    error_y="QuantitySold"
    

    This assumes your dataset includes a column like QuantitySold - which specifies how much uncertainty or fluctuation surrounds each revenue value.

    It’s a subtle but powerful way to convey confidence — and let your stakeholders know what’s real vs. what’s approximate.

  9. Challenge

    Step 8: Final Layout and Annotation Polish

    Step 8: Final Layout and Annotation Polish

    Your chart is functional and informative — now it's time to make it presentation-ready.

    In this step, you’ll learn how to refine visual details for a clean, professional look. These techniques are essential when you're preparing charts for executive meetings, stakeholder reviews, or published dashboards.

    You’ll apply layout changes that:

    • Improve legibility
    • Highlight key takeaways
    • Ensure formatting is consistent across all elements

    Plotly gives you granular control over:

    • Fonts, margins, and gridlines
    • Custom annotations
    • Tick formatting for currencies, percentages, or units

    These final touches turn a basic chart into a polished deliverable that communicates insights clearly and confidently.



    What You’ll Learn in This Step

    • Customize font sizes, margins, and grid visibility
    • Use add_annotation() to label important points
    • Format tick labels to match business conventions


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Apply Layout Updates for Font Size, Gridlines, and Margins

    Plotly charts are built for interactivity, but layout settings let you shape how the final output appears — especially in presentations or reports.

    You can use the update_layout() method to control overall styling elements like:

    • Font size: Use the font dictionary to set a consistent size across the chart.
    • Margins: The margin dictionary lets you define spacing around the plot (t, b, l, and r for top, bottom, left, and right).
    • Gridlines: Set xaxis_showgrid and yaxis_showgrid to show or hide background gridlines for each axis.

    These changes don’t affect the data or visuals directly — but they improve legibility, spacing, and consistency across multiple charts.

    Add Key Annotations to Highlight Specific Insights

    Annotations let you draw attention to important findings directly on the chart — such as a pricing threshold, a notable outlier, or a trend-breaking transaction.

    Plotly provides add_annotation() for adding text labels at any x/y location. You can position the label using x, y, and customize its appearance with optional parameters like text, showarrow, font, or arrowhead.

    Annotations are not tied to the data — they’re manual callouts that help your audience focus on what matters most.

    They’re especially useful when:

    • Presenting to stakeholders unfamiliar with the data
    • Highlighting exceptions or key takeaways
    • Explaining specific regions of the chart

    Unlike hover tooltips, annotations are always visible — making them ideal for storytelling.

    Apply Global Tick Formatting for Clarity

    Axes carry the most visible numbers in your chart — and when they’re hard to read, the message gets lost.

    Plotly allows you to control tick formatting using update_xaxes() and update_yaxes(). These methods let you adjust:

    • Tick prefix/suffix: Add units like $ or %
    • Number formatting: Round, group, or control decimal places
    • Tick angles and spacing: Improve fit and reduce clutter

    For example:

    fig.update_yaxes(tickprefix="$", tickformat=",")
    

    This applies a dollar sign and formats large numbers with commas (e.g., 1200 → $1,200).

    Global tick formatting ensures your axes are aligned with business expectations — and keeps your visualizations consistent across charts.

  10. Challenge

    Step 9: Build Animated Scatter Plots

    Step 9: Animate Sales Trends Over Time

    Charts don’t have to be static. Plotly supports animation — allowing you to show how patterns evolve over time using simple syntax.

    In this step, you’ll animate your scatter plot using the OrderDate column. Each frame of the animation will represent sales data from a different date — helping you observe trends, momentum, or anomalies across time.

    You’ll also reinforce skills from earlier steps:

    • Encode data using color and size
    • Overlay optional trendlines
    • Fine-tune animation speed and play controls

    This is a powerful way to transform static analysis into dynamic storytelling, ideal for dashboards and presentations.



    What You’ll Learn in This Step

    • Animate a scatter plot using animation_frame
    • Combine marker encodings with animation
    • Customize animation speed and layout controls


    info> Important: You must save your notebook (Ctrl/Cmd + S) before clicking Validate. Validation checks the most recent saved checkpoint.

    Dataset Overview

    | Column | Data Type | |------------------|-------------| | OrderID | string | | OrderDate | date | | ProductCategory | string | | DiscountPercent | float | | Revenue | float | | QuantitySold | int | | CustomerRegion | string |

    ### Animate a Scatter Plot Using `animation_frame`

    Plotly Express allows you to turn a static scatter plot into an animated sequence by using the animation_frame argument. This is especially useful when visualizing how data changes over time — such as tracking sales trends day-by-day.

    The argument works by splitting your dataset into distinct frames, based on the unique values in the column you provide. For example:

    px.scatter(df, x="DiscountPercent", y="Revenue", animation_frame="OrderDate")
    

    In this setup:

    • Each unique OrderDate becomes a frame in the animation
    • Points update automatically to reflect data from that specific date
    • Plotly adds a timeline slider and play/pause controls

    To use animation effectively:

    • Your animation_frame column should be categorical or discrete (dates should be pre-aggregated or grouped)
    • Ensure the frame column is formatted as strings or contains reasonable increments (e.g., daily or monthly)

    This creates a compelling way to show business performance unfolding over time, revealing trends, surges, or drops that would be hard to notice in a single static chart. ### Animate Marker Encodings for Richer Storytelling

    You’ve already learned how to map color, size, and other marker attributes to columns in your dataset. Now it’s time to combine those encodings with animation — so each frame not only reflects a different moment in time, but also reveals more layers of meaning.

    When you pass multiple arguments to px.scatter(), they continue working as the data shifts frame by frame:

    • color="ProductType" shows which product type each point represents
    • size="Revenue" scales each point based on revenue size
    • animation_frame="OrderDate" animates the chart across different dates

    Each frame of the animation now becomes a multi-dimensional snapshot — showing what was sold, how much it earned, and when it happened.

    This combination is ideal for tracking evolving business trends, such as:

    • Which product types dominate revenue on different days?
    • Are certain categories shrinking or growing over time?
    • Do high-revenue transactions cluster in particular periods?

    While trendlines aren’t compatible with animation, the movement of markers across frames often reveals patterns just as clearly.

    You're not just animating data — you're telling a dynamic story using multiple visual cues at once.

    Customize Animation Speed and Controls

    Once your animation is working, you can fine-tune how it behaves — adjusting transition speed and the appearance of playback controls.

    Plotly automatically adds a slider and play button when you use animation_frame, but you can customize them using the layout property.

    Here’s what you can adjust:

    • Transition Duration: Controls how smooth the transition is between frames
      Use transition=dict(duration=500)

    • Slider Options: Modify or style the timeline below the chart
      Use sliders=[dict(currentvalue={"prefix": "Date: "})] to show a custom label above the slider

    These options are useful when:

    • You want to slow down the animation for easier viewing
    • You want to label the date clearly under the slider
    • You want snappier transitions for faster storytelling

    Thoughtful pacing and clear controls make your data feel alive and understandable.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.