Matplotlib and Plotly are the two most popular ways to make charts in Python. Use Matplotlib when you need static, precisely controlled images for reports, slides and PDFs; use Plotly when you want interactive charts with hover details, zoom and filtering for the browser, notebooks or web dashboards. Most analysts end up using both, and this guide shows the same charts in each so you can decide quickly.
Matplotlib vs Plotly at a glance
| Feature | Matplotlib | Plotly |
|---|---|---|
| Output | Static images (PNG, SVG, PDF) | Interactive HTML; static images with an extra package |
| Interactivity | Minimal by default | Hover tooltips, zoom, pan and legend toggling built in |
| Quick API | df.plot() in pandas, plus seaborn on top | Plotly Express (px): one line per chart |
| Fine control | Excellent: every axis, tick and label | Very good via update_layout and update_traces |
| Best for | Reports, print, PDFs, academic figures, Power BI Python visuals | Exploration, notebooks, Streamlit and Dash apps, sharing HTML |
| Learning curve | Two interfaces (pyplot and object-oriented) can confuse beginners | Plotly Express is beginner-friendly; full graph objects take longer |
Both are free and open source. Install them with pip install matplotlib plotly; Anaconda includes them already. Many teams standardize on one library for reports and the other for exploration, which is a perfectly reasonable split. You do not need to master every option in either library; a handful of chart types (line, bar, scatter, histogram and box plot) covers most business questions.
Sample data for both libraries
All examples use a small pandas DataFrame of monthly sales by region. Replace it with pd.read_csv("your_file.csv") when you are ready.
import pandas as pd
import numpy as np
rng = np.random.default_rng(42)
df = pd.DataFrame({
"Month": pd.date_range("2025-01-01", periods=12, freq="MS").repeat(2),
"Region": ["East", "West"] * 12,
"Revenue": rng.integers(20_000, 60_000, size=24),
})
monthly = df.groupby("Month", as_index=False)["Revenue"].sum()
If pandas is new to you, our pandas tutorial for Excel users explains groupby and pivot_table.
Matplotlib: static charts with full control
Line chart
import matplotlib.pyplot as plt
from matplotlib.ticker import StrMethodFormatter
fig, ax = plt.subplots(figsize=(9, 4.5))
ax.plot(monthly["Month"], monthly["Revenue"], marker="o", linewidth=2)
ax.set_title("Monthly revenue")
ax.set_ylabel("Revenue")
ax.yaxis.set_major_formatter(StrMethodFormatter("${x:,.0f}"))
ax.spines[["top", "right"]].set_visible(False)
fig.tight_layout()
fig.savefig("monthly_revenue.png", dpi=200)
plt.show()
Notice the object-oriented style: you create a figure (fig) and axes (ax) and call methods on them. It is slightly longer than the quick plt.plot() style, but it scales cleanly to multi-chart layouts and is what most experienced users recommend.
Stacked bar chart by region
by_region = df.pivot_table(index="Month", columns="Region",
values="Revenue", aggfunc="sum")
by_region.index = by_region.index.strftime("%b")
fig, ax = plt.subplots(figsize=(9, 4.5))
by_region.plot(kind="bar", stacked=True, ax=ax, rot=0)
ax.set_title("Revenue by region")
ax.set_xlabel("")
fig.tight_layout()
plt.show()
Converting the date index to short month labels before plotting keeps the bar chart's axis tidy. The pandas .plot() method uses Matplotlib under the hood, so you can always fine-tune the result through ax.
Small multiples: one chart per region
fig, axes = plt.subplots(1, 2, figsize=(11, 4), sharey=True)
for ax, region in zip(axes, ["East", "West"]):
data = df[df["Region"] == region]
ax.plot(data["Month"], data["Revenue"], marker="o")
ax.set_title(region)
ax.tick_params(axis="x", rotation=45)
fig.suptitle("Monthly revenue by region")
fig.tight_layout()
plt.show()
Small multiples are often easier to read than one crowded chart with many lines. sharey=True puts both panels on the same scale, so readers can compare regions honestly instead of being misled by different axis ranges.
fig.savefig("chart.svg")) when they go into documents. Vector files stay sharp at any zoom level, while PNG at 200 dpi or more is a good choice for slides and email.Plotly: interactive charts in a few lines
Line chart
import plotly.express as px
fig = px.line(monthly, x="Month", y="Revenue", markers=True,
title="Monthly revenue")
fig.update_layout(yaxis_tickprefix="$", yaxis_tickformat=",.0f")
fig.show()
fig.write_html("monthly_revenue.html")
Stacked bar chart by region
fig = px.bar(df, x="Month", y="Revenue", color="Region",
title="Revenue by region")
fig.show()
Plotly Express takes the "long" DataFrame directly and stacks the bars by color automatically, so no pivot is needed. Hover over any bar to see its exact value, click a legend item to hide a region, and drag to zoom. The saved HTML file opens in any browser, which makes it easy to share an interactive chart with someone who does not use Python.
Exporting a Plotly chart as a static PNG requires the extra kaleido package (pip install kaleido) and then fig.write_image("chart.png").
Customizing hover labels and reference lines
avg = df["Revenue"].mean() # average per region per month
fig = px.line(df, x="Month", y="Revenue", color="Region",
markers=True, template="plotly_white")
fig.add_hline(y=avg, line_dash="dash", annotation_text="Average")
fig.update_traces(hovertemplate="%{x|%b %Y}<br>$%{y:,.0f}")
fig.show()
hovertemplate controls exactly what appears in the tooltip, and add_hline draws a reference line such as a target or average. The average is calculated from the same per-region monthly values the lines show, so the comparison is fair.
How to choose: a simple decision guide
- Where will the chart live? A PDF, printed report or Word document points to Matplotlib. A browser, notebook or web app points to Plotly.
- Will people explore it? If readers need to hover for exact values or zoom into a date range, choose Plotly.
- Is it going into Power BI? Power BI's Python visual renders static images through Matplotlib (or libraries built on it, such as seaborn). See Python and R Visuals in Power BI.
- Are you building a dashboard app? Plotly integrates naturally with Dash and Streamlit; see Build Web Dashboards with Streamlit.
- Do you need a publication-quality figure with exact styling? Matplotlib gives you control over every pixel.
Whichever library you pick, the design principles are the same: one clear message per chart, a descriptive title, labeled axes, minimal clutter and color used with purpose.
Common chart mistakes in both libraries
- Truncated bar axes: bar charts should start at zero; otherwise small differences look dramatic. Matplotlib and Plotly both usually start bars at zero, but check after you set custom limits.
- Too many colors: more than five or six series in one chart becomes hard to read. Group minor categories into "Other" or switch to small multiples.
- Unformatted numbers: raw values like 1234567.891 on an axis slow readers down. Use the tick formatting shown above.
- Default titles: a title such as "Revenue" says little. A title like "West revenue fell in Q3" tells the reader what to notice.
For more on these principles, see Data Visualization Principles That Actually Work.
Where seaborn fits
seaborn is a statistical plotting library built on Matplotlib. It produces attractive histograms, box plots, heatmaps and regression plots with very little code, for example sns.boxplot(data=df, x="Region", y="Revenue"). Because its output is a Matplotlib figure, you can customize it with the same ax methods shown above and use it anywhere Matplotlib works, including Power BI Python visuals.
Next steps
Take one chart you rebuild by hand every month and recreate it in both libraries using the code above. Save the Matplotlib version as a PNG for your report and the Plotly version as HTML for colleagues who like to explore. Once you know which one your audience prefers, turn the script into a reusable function so next month's chart takes seconds.
Watch: video lessons


Frequently asked questions
Is Plotly better than Matplotlib?
Neither is better overall. Plotly is stronger for interactive, browser-based charts, while Matplotlib is stronger for static, precisely styled images for reports and print.
Is Plotly free?
Yes, the Plotly Python library is open source and free to use, including offline. The company behind it also sells commercial products such as Dash Enterprise, but you do not need them to make charts.
Can I use Plotly in Power BI Python visuals?
Power BI's Python visual displays static images drawn on the default plotting device, so Matplotlib and seaborn are the standard choices there. Use Plotly in notebooks, HTML files and web apps instead.
How do I save a Plotly chart as an image?
Install the kaleido package with pip install kaleido, then call fig.write_image("chart.png"). To keep the chart interactive, use fig.write_html("chart.html") instead.
Mark this lesson complete to track your rank progress.