- Lab
- Data

Build a Bubble Chart in Python to Visualize Startup Funding and Valuation Trends
In this Code Lab, you'll learn to create a professional bubble chart in Python using Plotly. You'll walk step by step through building, styling, and enhancing a visualization that shows how startup funding relates to valuation and investor interest. By the end, you'll have a polished, interactive chart ready for presentations and data storytelling.

Path Info
Table of Contents
-
Challenge
Step 1: Building the Basic Bubble Chart
Step 1: Create a Basic Bubble Chart
To begin your analysis, you’ll create a basic bubble chart that compares startup funding and valuation. Bubble charts are ideal for exploring multi-dimensional data—especially when you want to emphasize both magnitude and relationship.
You’ll use Plotly Express to generate a chart that maps total funding against company valuation, while encoding the number of funding rounds into the bubble size. This gives an immediate sense of both scale and investment activity across startups.
What You’ll Learn in This Step
- Create a bubble chart using
px.scatter()
- Assign axes and bubble size using column names
- Pass a label to help identify each point
- Render the chart with
fig.show()
#### Open the NotebookFrom the workspace panel, open the notebook file:
1-step-one.ipynb
.info> Important: You must save your notebook (Control or Command+S) before clicking Validate. Validation checks the most recent saved checkpoint.
### Starting the Bubble Chart: Create a Basic Scatter PlotHow to Complete Each Task
- Find the matching code cell labeled Task 1.X.
- Complete the missing code by following the
# TODO
comments in the cell. - Run the cell using the Run button or by pressing
Shift+Enter
. - Save your progress using the Save icon or by selecting File > Save and Checkpoint.
- All code and output will appear inline in the notebook.
A scatter plot is the foundational structure for a bubble chart. It compares two numeric variables using Cartesian coordinates.
In this task, you'll create a basic scatter plot to explore the relationship between startup funding amounts and company valuations.
The
plotly.express.scatter()
function from the Plotly Express library is used to generate the chart.Required Parameters
x
: The column for the horizontal axisy
: The column for the vertical axis
#### Parameter Notesfig = px.scatter( dataframe, x="column1", y="column2" )
dataframe
: The Pandas DataFrame containing the datacolumn1
andcolumn2
: Numeric fields to visualizefig
: The resulting Figure object
#### Parameter Notesfig.show() ``` ### Encoding Bubble Size in a Scatter Plot To convert a basic scatter plot into a bubble chart, a third numeric variable is used to represent the size of each point. The `size` parameter in `plotly.express.scatter()` enables visualization of this third numeric dimension by scaling each marker proportionally. </br> #### How Bubble Size Works - The `size` argument accepts the name of a numeric column. - Larger values in that column produce larger bubbles. - Plotly automatically scales bubble sizes, but you can fine-tune the scaling using the size_max parameter. </br> #### Syntax Example ```python fig = px.scatter( dataframe, x="column1", y="column2", size="column3" )
column3
must contain non-negative numeric values (e.g., counts, scores, revenue).- The chart remains a 2D scatter plot, but now includes a third visual encoding via bubble size.
Applying Color Grouping with the
color
ParameterIn a bubble chart, color can be used to group or differentiate data based on a categorical variable. Plotly Express provides the
color
parameter for this purpose.This adds an additional layer of meaning by visually separating data points by category such as industry type, region, or status.
How the
color
Parameter Works- Accepts the name of a column with categorical values (strings or discrete labels).
- Automatically assigns distinct colors to each category.
- Generates a color legend for reference.
#### Parameter Notesfig = px.scatter( dataframe, x="column1", y="column2", size="column3", color="category_column" )
category_column
should contain short, interpretable labels.- Plotly will automatically encode the legend and assign colors accordingly.
- The
color
parameter works alongside withsize
, allowing multiple dimensions in the same chart. ### Adding Custom Hover Labels withhover_name
Interactive charts often display tooltips when hovering over data points. The
hover_name
parameter in Plotly Express allows you to specify which column’s values should appear as the main label in the tooltip.This is especially useful for identifying individual records—such as like startup names—without crowding the chart visually.
How
hover_name
Works- Accepts a column name with descriptive labels, such as names or IDs.
- The column’s values appear prominently when hovering over a point.
- Supports string or numeric data types.
- Create a bubble chart using
-
Challenge
Step 2: Customizing Appearance and Style
Step 2: Customize Appearance and Style
Now that the core bubble chart is in place, the next step is to improve its readability and visual appeal.
In this step, you’ll adjust the bubble size scaling, apply a company-branded color palette, customize the chart’s title and axis labels, and apply a visual theme with opacity adjustments. These enhancements are essential for making charts presentation-ready and aligned stakeholder or brand guidelines.
What You’ll Learn in This Step
- Control bubble size scaling using
size_max
- Apply a predefined or custom color palette
- Set axis labels and chart titles using
update_layout()
- Apply visual themes and marker styling using Plotly options
#### Open the NotebookFrom the workspace panel, open the notebook file:
2-Step-two.ipynb
.info> Reminder: You must save your notebook (Control or Command+S) before clicking Validate.
### Controlling Maximum Bubble Size with `size_max`How to Complete Each Task
- Find the matching code cell labeled Task 2.X.
- Complete the missing code by following the
# TODO
comments inside the cell. - Run the cell to preview the updated chart.
- Save your work before validating each task.
When using the
size
parameter inplotly.express.scatter()
, Plotly automatically scales bubble sizes based on the data. However, the largest bubbles can sometimes overpower the chart or overlap others.The
size_max
parameter allows you to set a fixed maximum bubble diameter (in pixels), helping to maintain clarity and visual balance.Usage Example
#### Parameter Notesfig = px.scatter( dataframe, x="column1", y="column2", size="column3", size_max=50 )
size_max
accepts a numeric value (e.g., 40, 60, 100).- Affects only the visual scaling—it does not alter the underlying data.
- Default value is 20. Increasing it makes large bubbles appear more prominent. ### Applying a Custom Brand Palette with
color_discrete_sequence
Plotly allows full customization of category colors using the
color_discrete_sequence
parameter. This is useful when aligning charts with a company’s visual identity or brand guidelines.You can pass a list of valid CSS color names or hex codes to control the order and appearance of category colors in the chart.
Custom Palette Syntax
#### Usage in `px.scatter()`company_colors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728"]
#### Parameter Notes * `color_discrete_sequence` must be a list of valid color codes. * Colors are assigned in the order they appear in the list. * This only applies to categorical data in the `color` argument. ### Using a Predefined Plotly Color Palette and Adding Chart Labelsfig = px.scatter( dataframe, x="column1", y="column2", size="column3", color="category_column", color_discrete_sequence=company_colors )
Plotly provides built-in color palettes under the
px.colors.qualitative
module. These color sequences are designed for categorical data—meaning they help visually separate distinct groups like product names, regions, or industries.In this task, you’ll use a palette called
Bold
, which features high-contrast colors that are easy to distinguish.You’ll also use the
update_layout()
method to improve the chart's readability by customizing the axis labels and chart title.Set the Color Palette
custom_colors = px.colors.qualitative.Bold
- This assigns a pre-configured list of vivid colors to your
custom_colors
variable. - These colors will be used when rendering the
Industry
categories in your chart.
fig.update_layout( title="Startup Funding vs. Valuation", xaxis_title="Total Funding ($M)", yaxis_title="Company Valuation ($M)" )
title
: Sets the top-level title of the chartxaxis_title
,yaxis_title
: Replace default axis labels with clear, professional text
### Applying Themes and Adjusting Marker OpacityAbout Plotly Qualitative Color Palettes
Qualitative color scales are designed for categorical data—they provide visually distinct colors for each unique label or group.
The
px.colors.qualitative
module includes several options, each with its own color feel:px.colors.qualitative.Bold # High-contrast, bright palette px.colors.qualitative.Pastel # Light, muted tones px.colors.qualitative.Set1 # Similar to ColorBrewer Set1 px.colors.qualitative.Dark24 # For high-cardinality categories (24 total) px.colors.qualitative.Prism # Vivid, non-repeating palette
- Use
Bold
when you want the chart to “pop” with saturated colors. - Use
Pastel
when a softer tone is preferable for context or accessibility. - Use
Dark24
when you have many categories and still want distinct colors.
You can preview these palettes by printing them in a notebook:
print(px.colors.qualitative.Bold)
Plotly Express charts can be styled visually using the
template
parameter. Templates control overall appearance, including background color, font, gridlines, and contrast—all without changing your data or axes.This task also introduces marker-level styling. By lowering
opacity
, you can reduce visual noise caused by overlapping points.Applying a Theme
fig = px.scatter( dataframe, x="column1", y="column2", template="plotly_dark" )
- The
template
parameter accepts a string corresponding to built-in Plotly theme. - Themes are useful when preparing charts for presentations or dark-mode dashboards.
Adjusting Opacity
fig.update_traces(marker=dict(opacity=0.7))
- Use values between
0
(fully transparent) and1
(fully opaque). - Lower opacity helps distinguish clusters and overlapping points.
🎨 Plotly Theme Options
These themes are available by default in Plotly:
| Theme Name | Description | | ---------------- | --------------------------------------------------------- | |
"plotly"
| The default theme with a white background and gridlines. | |"plotly_dark"
| Dark background, high contrast—great for presentations. | |"ggplot2"
| Styled after the ggplot2 library in R. | |"seaborn"
| Inspired by Seaborn aesthetics (subtle and clean). | |"simple_white"
| Minimalist white background with no gridlines. | |"presentation"
| Bold fonts and layout tuned for slide decks. | |"none"
| Disables all theming—use when building from scratch. |To preview a theme, just assign it to the
template
parameter and rerun the chart. - Control bubble size scaling using
-
Challenge
Step 3: Enhancing Interactivity and Layout
Step 3: Enhance Interactivity and Layout
Now that the visual design is polished, you’ll improve how users explore and interpret the chart.
This step focuses on enhancing readability and interactivity. You’ll apply a log scale to spread out clustered values, split the chart by region using facets, and activate advanced viewer options like scroll zoom and responsive layout.
These improvements make it easier to analyze trends and compare startup performance across different regions and funding levels.
What You’ll Learn in This Step
- Use log scaling to improve spread and reveal smaller values
- Break charts into small multiples using
facet_row
parameter - Enable scroll zoom and responsive behavior in the notebook
Open the Notebook
From the workspace panel, open the notebook file:
3-Step-three.ipynb
.info> Reminder: You must save your notebook (Control or Command+S) before clicking Validate.
### Adjusting Layout: Legend Position, Margins, and FontHow to Complete Each Task
- Locate the correct code cell labeled Task 3.X.
- Follow the
# TODO
comments to implement the required changes. - Run the cell to preview the updated chart.
Customizing chart layout helps you control how your visual appears in presentations or dashboards. In Plotly, layout-level changes are made using the
update_layout()
method.This method allows you to fine-tune non-data elements such as:
- Legend positioning
- Chart margins
- Font size and styling
Legend Position
legend=dict(x=0.02, y=0.98)
x
andy
are in relative coordinates (0
to1
).- This places the legend in the top-left corner of the chart.
Margin Settings
margin=dict(l=40, r=40, t=60, b=40)
- Controls the spacing between the chart and notebook edges.
Font Size
font=dict(size=14)
- Increases legibility for labels, axes, and legends text.
You can pass all of these into a single call to
fig.update_layout()
to apply visual improvements at once. ### Customizing Hover Labels for ClarityBy default, Plotly shows all visible chart fields in hover tooltips. You can customize these tooltips to highlight only the most relevant information for your audience.
This is done using the
hover_name
andhover_data
parameters inpx.scatter()
.Key Parameters
hover_name="StartupName", hover_data={"InvestorsCount": True, "Industry": True}
hover_name
controls the main bold label in the tooltip.hover_data
allows you to specify which additional columns appear, and whether to format or rename them.- You can pass a dictionary to
hover_data
with column names as keys and Boolean as values.
Setting a value to
True
includes the column in the hover. Setting it toFalse
hides it—even if it’s used elsewhere in the chart.Example Output
This configuration will display:
- The startup name in bold
- Number of investors and the industry below
Adjusting Marker Opacity and Styling
In Plotly, visual emphasis can be enhanced using trace-level styling via
update_traces()
method. This allows you to change how all markers in the figure appear, such as their transparency, border, and outline color.Key Options for
update_traces()
fig.update_traces( marker=dict( opacity=0.6, line=dict(width=1, color="white") ) )
opacity
: Controls marker transparency (0
= fully transparent,1
= fully opaque).line.width
: Adds an outline around each bubble.line.color
: Sets the border color.
This method is useful when you want bubbles to overlap more cleanly or stand out better against dark themes. ### Making Charts Interactive with Layout Options
Plotly charts can behave more like web apps when you enable interactivity options. You can control things like scroll zoom, responsiveness, and resizing behavior using the
fig.update_layout()
method with special parameters.Enabling Scroll Zoom
fig.update_layout( dragmode="zoom", hovermode="closest" )
This makes scroll-to-zoom active and improves how users explore dense charts.
Making the Chart Responsive
fig.update_layout( autosize=True )
This allows the chart to adjust to the size of the display, especially helpful in dashboards or resizable interfaces.
You can also explicitly enable web responsiveness using:
fig.update_layout( uirevision=True )
This preserves the current view even after the chart is updated, which is great for interactive notebooks and apps.
-
Challenge
Step 4: Creating Advanced Bubble Charts with Graph Objects
Step 4: Creating Advanced Bubble Charts with Graph Objects
For more advanced control over your chart’s behavior and style, you can use Plotly’s lower-level
graph_objects
(orgo
) interface.Unlike
plotly.express
, which abstracts many details for speed and ease,graph_objects
allows you to directly configure every visual and interactive property of a chart.This is useful when you need custom marker sizing, conditional formatting, or dynamic hover labels that aren’t possible through Express.
What You’ll Learn in This Step
- Build a bubble chart manually using
go.Scatter
- Adjust marker size behavior using
sizeref
,sizemode
, andsizemin
- Add marker borders and hover templates for pixel-perfect control
Open the Notebook
From the workspace panel, open the notebook file:
4-Step-four.ipynb
.info> Reminder: You must save your notebook (Control or Command+S) before clicking Validate.
### Building a Bubble Chart with graph_objectsHow to Complete Each Task
- Find the matching code cell labeled Task 4.X
- Follow the
# TODO
comments in each code cell to implement the required changes. - Run the cells and save your notebook frequently.
Unlike
plotly.express
, theplotly.graph_objects
(orgo
) interface provides low-level control over how your chart is constructed and styled.In this task, you’ll manually create a bubble chart using
go.Scatter
. This function expects separate arguments for each trace property and gives you full flexibility in formatting.Creating a Basic go.Scatter Chart
import plotly.graph_objects as go fig = go.Figure( go.Scatter( x=dataframe["column_x"], y=dataframe["column_y"], mode="markers", marker=dict(size=dataframe["size_column"]) ) )
mode="markers"
ensures that no lines are drawn—only points.marker.size
controls the size of each bubble.- The chart is wrapped in
go.Figure()
to initialize the figure and render it.
You’ll use this foundation in later tasks to configure advanced sizing and interactivity. ### Customizing Bubble Size with Marker Settings
When using
plotly.graph_objects
, you gain full control over how marker sizes are interpreted and scaled.This task introduces three important properties:
1.
sizemode="area"
Specifies how to scale bubble sizes:
"diameter"
(default): Size is applied to diameter directly."area"
(recommended): Size values map to bubble's area, which creates more accurate visual comparisons.
2.
sizeref
A scaling factor used to normalize bubble sizes within the plot. The formula to determine a good
sizeref
value is:sizeref = 2.0 * max_size_value / (desired_max_size ** 2)
Example:
sizeref = 2.0 * df["InvestorsCount"].max() / (60 ** 2)
This ensures the largest bubble is no wider than 60 pixels.
3.
sizemin
Sets the smallest visible marker size (in pixels). Use this to prevent small values from disappearing entirely. ### Adding Custom Marker Borders in
graph_objects
When you use
plotly.graph_objects
, each marker can be enhanced with a border (or "stroke") for better contrast and visibility.How Marker Borders Work
The
marker.line
dictionary allows you to control the following properties:width
: The stroke thickness (in pixels)color
: The stroke color (e.g.,"white"
)
Example Syntax
marker=dict( size=dataframe["column"], sizemode="area", sizeref=sizeref, sizemin=4, line=dict(width=1, color="white") )
Why use marker borders?
- They make bubbles stand out, especially on dark or visually dense charts.
- They help differentiate overlapping markers more clearly. ### Building Custom Hover Templates in
graph_objects
When you need precise control over tooltips,
graph_objects
allows you to format hover text using thehovertemplate
property.How
hovertemplate
WorksUnlike
hover_name
orhover_data
inplotly.express
, thehovertemplate
string uses Jinja-style variable placeholders like%{x}
,%{customdata[0]}
, etc.You can display multiple fields, include units, and control the order and labels.
Key Concepts
%{x}
and%{y}
refer to the values of the x and y axes.%{customdata[0]}
accesses additional data you pass through thecustomdata
argument.hovertemplate
must end with<extra></extra>
to suppress the default trace label.
Example
customdata = df[["Industry", "Region"]].values hovertemplate = ( "Funding: %{x}<br>" + "Valuation: %{y}<br>" + "Industry: %{customdata[0]}<br>" + "Region: %{customdata[1]}<extra></extra>" )
- Build a bubble chart manually using
-
Challenge
Step 5: Exploring Animations and 3D Views
Step 5: Exploring Animations and 3D Views
Now that you’ve built interactive 2D visualizations, it’s time to explore some of Plotly’s more advanced capabilities.
This step introduces animated and 3D bubble charts—both are great tools for presenting time-based data or giving your charts a visual “wow” factor.
You’ll also practice combining multiple traces in one figure, giving you more flexibility when visualizing comparisons or layered information.
What You’ll Learn in This Step
- Animate a chart using
animation_frame
- Create a 3D bubble chart with
px.scatter_3d()
- Combine multiple traces with
graph_objects
Open the Notebook
From the workspace panel, open the notebook file:
5-Step-five.ipynb
.info> Reminder: You must save your notebook (Control or Command+S) before clicking Validate.
### Creating Animated Bubble Charts with `animation_frame`How to Complete Each Task
- Find the matching code cell labeled Task 5.X.
- Follow theÂ
# TODO
 comments to implement the required changes. - Run your chart and save the notebook to validate.
Animated charts help you visualize changes across categories or time slices. Plotly’s
animation_frame
parameter allows you to create frame-by-frame transitions from your dataset.How It Works
The
animation_frame
parameter tells Plotly to draw one frame per unique value in a given column. This column must be categorical or time-based.For example, if your dataset has a column like:
df["ValuationCheckQuarter"].unique() # ['Q1', 'Q2', 'Q3', 'Q4']
You can use it like this:
fig = px.scatter( dataframe, x="column1", y="column2", size="column3", animation_frame="ValuationCheckQuarter" )
Each unique quarter will animate a different view of your chart.
Notes
- The
animation_frame
column must be non-null and contain distinct, interpretable values. - You can combine this with hover labels, sizing, and coloring just like normal. ### Creating 3D Bubble Charts with
px.scatter_3d
3D scatter plots allow you to explore multi-variable data by mapping an additional variable to the z-axis. This can reveal clusters, ranges, or outliers that are not obvious in 2D.
How It Works
Plotly Express provides a function called
px.scatter_3d()
, which works likepx.scatter()
but accepts three axes:x
,y
, andz
.Example syntax:
fig = px.scatter_3d( dataframe, x="column1", y="column2", z="column3", size="column4", color="column5" )
Notes
- You can rotate, zoom, and pan in all 3 dimensions.
- Use
size_max
to control bubble scale in 3D. - The
x
,y
, andz
axes should contain numeric values. ### Combining Multiple Traces in a Single Figure
In Plotly, a trace is a single series of data—for example, a group of bubbles representing one category. By combining multiple traces, you can compare distinct groups in a single visualization.
How It Works
Using
plotly.graph_objects
, you can explicitly add each trace usingadd_trace()
. This gives you control over how each group is styled and labeled.Example syntax:
import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter( x=data1["x"], y=data1["y"], mode="markers", name="Group 1" )) fig.add_trace(go.Scatter( x=data2["x"], y=data2["y"], mode="markers", name="Group 2" )) fig.show()
Each call to
add_trace()
adds a new layer to the chart. This is especially useful when comparing categories like industries, product types, or user segments. - Animate a chart using
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.