Plotly is a Python library for creating interactive visualizations. It is widely used in analytics, data science, business intelligence, dashboards, and reporting because it allows users not only to see a chart, but also to interact with it.
Unlike static plotting libraries, Plotly charts allow the audience to:
hover over data points to see exact values
zoom into specific regions
pan across the chart
hide or show categories from the legend
inspect complex charts more carefully
This makes Plotly especially useful when we want to move beyond simple chart display and support deeper data exploration.
it works very naturally with Pandas DataFrames, which means analysts can move directly from cleaned and transformed data into visualization.
it supports a wide variety of chart types, from basic charts to more advanced business and analytical visuals.
Plotly is highly useful in modern Python applications such as:
Jupyter notebooks
Quarto documents
Dash applications
Streamlit applications
So Plotly is not only a charting library. It is also part of a larger ecosystem for analytical communication and interactive reporting.
Static vs Interactive Visualization
A useful way to understand Plotly is to compare static and interactive charts.
A static chart gives one fixed view. It is suitable for printed reports, PDFs, or slides where the figure is meant to be consumed passively.
An interactive chart gives the user control. The reader can inspect exact values, focus on specific sections, or compare categories dynamically.
This does not mean interactive charts are always better. It means that Plotly is particularly strong when the audience benefits from exploration.
Plotly Architecture
Plotly in Python is usually used in two main ways:
Plotly Express
Graph Objects
Plotly Express
Plotly Express is the high-level interface.
It is designed to make chart creation fast, concise, and readable. In many cases, a complete interactive chart can be built in a single line.
It is especially useful when:
the data is already tidy
the goal is to build a standard chart quickly
we want to map variables to color, size, symbol, or facets in a simple way
Plotly Express is often the best starting point for analysts because it reduces boilerplate and helps students focus on chart logic rather than technical details.
Graph Objects
plotly.graph_objects is the lower-level interface.
It provides more control and flexibility. It is useful when:
we need custom traces
we want complex layouts
we need subplots
we want advanced annotations or specialized visual structures
In practice, many analysts start with Plotly Express and move to Graph Objects when they need more control.
Plotly and the Grammar of Graphics
Plotly also connects well to the idea of the grammar of graphics.
Instead of thinking only in terms of chart names, we can think in terms of components:
data: the table behind the chart
mapping: how variables are assigned to axes or visual properties
geometry: bars, lines, points, areas, flows
aesthetics: color, size, labels, symbols
annotations: average lines, reference markers, labels, notes
This way of thinking is useful because it teaches students that charting is not only about memorizing functions. It is about translating business questions into visual structure.
Common Chart Families in Plotly
Plotly supports many chart families. Some of the most common are:
bar plots for category comparison
line plots for trends over time
histograms for distributions
scatter plots for relationships between variables
multi-line charts for comparing trends across groups
These chart types form the foundation of most analytical reporting.
A Practical Workflow
A common analytical workflow with Plotly looks like this:
This reminds students that visualization is not the first step. Plotly becomes most useful after the data is already structured for analysis.
Dummy Dataset for Plotly Examples
Before introducing the major chart types, let us create a small synthetic dataset.
import pandas as pdimport numpy as npimport plotly.express as pxnp.random.seed(42)px.defaults.template ="plotly_white"months = pd.date_range("2024-01-01", periods=6, freq="MS")regions = ["North", "South", "East"]products = ["A", "B"]rows = []for month in months:for region in regions:for product in products: sales = np.random.randint(80, 220) customers = np.random.randint(20, 90) units = np.random.randint(10, 70) rows.append([month, region, product, sales, customers, units])df_plotly = pd.DataFrame( rows, columns=["month", "region", "product", "sales", "customers", "units"])df_plotly["month_name"] = df_plotly["month"].dt.strftime("%b")df_plotly.head()
month
region
product
sales
customers
units
month_name
0
2024-01-01
North
A
182
71
38
Jan
1
2024-01-01
North
B
94
80
30
Jan
2
2024-01-01
South
A
182
43
12
Jan
3
2024-01-01
South
B
132
21
33
Jan
4
2024-01-01
East
A
117
21
69
Jan
This dummy dataset gives us:
a time variable: month
categorical variables: region, product
numeric variables: sales, customers, units
This structure is enough to introduce the most common chart types in Plotly.
Random Seed
WarningRandom Seed
What does it mean np.random.seed(42)?
Computers are not truly random. They use algorithms called pseudo-random number generators (PRNGs).
These algorithms:
Take an initial value → the seed
Then produce a sequence of numbers based on it
If you use the same seed, you get exactly the same sequence every time
Plotly Templates
Here you can explore plotly templates. In the scope of this program we will stick with the plotly_white. However I highly encourage you to explore other themes and adjust for your prjects:
px.defaults.template ="plotly_white"
The default template is 'plotly'
Available templates:
‘ggplot2’
‘seaborn’
‘simple_white’
‘plotly’,
‘plotly_white’
‘plotly_dark’
‘presentation’
‘xgridoff’,
‘ygridoff’
‘gridon’
‘none’
Example 1: Bar Plot
A bar plot is used when we want to compare values across discrete categories.
Typical examples include:
sales by region
customers by segment
revenue by product category
A bar plot is useful when we want to compare values across categories.
For this example, we may want to compare total sales across regions.
A grouped bar plot extends the basic bar plot by introducing one more categorical variable. Instead of showing only one bar per category, it allows us to compare subgroups inside each main category.
For example, we may want to compare sales by region and product at the same time. This helps us answer not only which region performs better, but also whether the same pattern holds across products.
Before executing the code, let us understand the key arguments of px.pie() in this example.
data_frame = the dataset used for plotting
names = the categorical variable that defines the slices
values = the numeric variable that determines slice sizes
hole = controls the size of the empty center and turns the pie chart into a donut chart
title = chart title
In our example:
names="product" means each slice represents a product
values="sales" means slice size depends on total sales
hole=0.5 creates the donut shape
Try It Yourself
Students should experiment with the following changes:
change values="sales" to values="customers" or values="units"
change hole=0.5 to hole=0.2 or hole=0.7
change names="product" to names="region" after preparing a suitable aggregated table
change the title to reflect the new chart meaning
fig = px.pie( product_sales, names="product", values="sales", hole=0.5, title="Share of Total Sales by Product")fig.update_traces(textinfo="label+percent")fig.show()
Changing Colors in Plotly
In Plotly, colors can be changed in several ways depending on the chart type and how much control you want.
color_discrete_sequence=["steelblue"] tells Plotly to use one color
you can replace "steelblue" with any valid CSS color name or hex code
TipTry It Yourself
Change "#a34e31" to:
"orange"
"green"
"#3B6EAD"
"#B7C2D1"
Different Colors by Category
If your chart uses a grouping variable such as color="product" or color="region", Plotly automatically assigns colors.
You can override those defaults with color_discrete_sequence.
Checkout bellow Grouped Bar Plot with Custom Colors
fig = px.bar( region_product_sales, x="region", y="sales", color="product", barmode="group", title="Sales by Region and Product", color_discrete_sequence=["#3B6EAD", "#AFC4E8"])fig.show()
Here:
the first category gets the first color
the second category gets the second color
Map Specific Categories to Specific Colors
If you want full control over which category gets which color, use color_discrete_map. In other words we can have Fixed Colors for Products
fig = px.bar( region_product_sales, x="region", y="sales", color="product", barmode="group", title="Sales by Region and Product", color_discrete_map={"A": "#3B6EAD","B": "#AFC4E8" })fig.show()
This is often better than color_discrete_sequence when you want consistency across many charts.
fig = px.histogram( df_plotly, x="sales", nbins=15, title="Distribution of Sales", color_discrete_sequence=["purple"])fig.show()
Change Scatter Plot Colors
fig = px.scatter( df_plotly, x="customers", y="sales", title="Customers vs Sales", color_discrete_sequence=["darkorange"])fig.show()
fig = px.scatter( df_plotly, x="customers", y="sales", color="region", title="Customers vs Sales by Region", color_discrete_sequence=["#3B6EAD", "#AFC4E8", "#B7C2D1"])fig.show()
Change Colors After the Figure is Created
You can also modify colors after building the figure.
Example 1: Update Trace Color
fig = px.bar( region_sales, x="region", y="sales", title="Total Sales by Region")fig.update_traces(marker_color="teal")fig.show()
Example 2: Update Trace Color
fig = px.line( monthly_sales, x="month", y="sales", title="Monthly Total Sales")fig.update_traces(line_color="red")fig.show()
Recommendtion
A practical rule for learning is:
use color_discrete_sequence when you just want nicer colors
use color_discrete_map when you want specific categories to always keep the same colors
use update_traces() when you want to modify the figure after it is already created
TipTry yourself
Take one of your earlier charts and try all of the following:
apply one single custom color
apply two category colors
map exact colors to product names
update the color after the figure is created
This helps you to understand that color in Plotly is not fixed. It is another argument they can control.
Highlighting Only the Specific Categories
Sometimes we want to guide the audience’s attention very deliberately. Instead of giving every category a different color, we can keep most categories in a neutral tone and highlight only the largest/smallest category.
This is a very useful analytical design technique because it helps the chart communicate one main message clearly.
It is especially useful when:
we want to emphasize the top-performing category
we want to reduce visual clutter
we want to make the most important comparison obvious
we want to keep the chart clean and readable
The same logic can be reused across multiple chart types.
The general pattern is:
aggregate the data
find the category with the highest/lowest value
create a helper column for coloring
assign one color to the largest category and another color to the rest
Highlighting the Largest Category in a Bar Plot
Preparing the Data
A bar plot is one of the most natural places to use this technique.
Build a summary table by Region: as_index=False the region stays normal column
Find the region with the highest sales: top_region would provide the largest value (idxmin() would return the lowest valued region)
For a simple line chart, there is only one line, so highlighting a category is not applicable in exactly the same way. But we can highlight the maximum point instead.
highlight the top product instead of the top region
change the highlighted color
change line width using update_traces()
Building the Plot
fig = px.line( monthly_region_sales, x="month", y="sales", color="highlight", markers=True, title="Highlighting Only the Largest Category", color_discrete_map={ top_region: "#3B6EAD","Other Regions": "#D9D9D9" })fig.update_layout( xaxis_title="Month", yaxis_title="Sales", legend_title="")fig.show()
Highlighting the Largest Category in a Histogram
A histogram shows a distribution, so categories are not always directly visible. But if we color observations by whether they belong to the largest category, we can compare the highlighted group against all others.
fig = px.bar( region_product_sales, x="region", y="sales", color="highlight", barmode="group", title="Highlighting Only the Largest Category", color_discrete_map={ top_product: "#3B6EAD","Other Products": "#D9D9D9" })fig.update_layout( xaxis_title="Region", yaxis_title="Sales", legend_title="")fig.show()
Vertical and Horizontal Reference Lines
Sometimes a chart becomes much more useful when we add a reference line. A reference line helps us move beyond simply displaying values and begin interpreting them.
Vertical and horizontal lines are commonly used to show:
average values
targets or thresholds
important dates
campaign launch points
policy changes
before-and-after comparisons
These lines are not decorative. They are analytical tools. They help the audience answer questions such as:
Which observations are above average?
Which values are below the target?
What happened after a major event?
Did the pattern change after a certain date?
Why Reference Lines Matter
A chart without a reference line may show a pattern, but a chart with a reference line often shows meaning more clearly.
For example:
a line chart of monthly sales shows trend
a line chart of monthly sales with an average line shows which months performed above or below the overall benchmark
a line chart with a campaign start marker helps separate pre-campaign and post-campaign periods
So reference lines help connect the chart to a business question.
Horizontal Lines
A horizontal line is usually used to show a benchmark on the y-axis.
Common examples include:
average sales
target revenue
minimum acceptable performance
upper control limit
lower control limit
Suppose we want to examine monthly sales and compare each month against the average monthly sales.
Is performance consistently above the benchmark or not?
Vertical Lines
A vertical line is usually used to mark a specific point on the x-axis.
Common examples include:
campaign start date
product launch date
policy change date
market shock
start of a promotion
When the x-axis is time, vertical lines are especially useful.
Suppose a campaign started on April 1, 2024, and we want to mark that point on the chart.
Important Note
Important
When working with Plotly and datetime axes, add_vline() with annotation_text=... may raise errors in some environments. A safer and more reliable pattern is:
add the vertical line with fig.add_vline()
add the label separately with fig.add_annotation()
Understanding the Main Arguments
For the vertical line:
x = the x-value where the vertical line will be placed
line_dash = the style of the line
line_color = the color of the line
For the annotation:
x = where the label points
y = the vertical position of the label anchor
text = label text
showarrow=True = displays an arrow
ax and ay = control the arrow direction and text position