Python & AI

Charts in Python: Matplotlib vs Plotly

Matplotlib vs Plotly compared for analysts: static vs interactive charts, side-by-side line and bar examples, export options and how to pick the right one.

By DashCore Hub Editorial TeamUpdated 7 min read

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

FeatureMatplotlibPlotly
OutputStatic images (PNG, SVG, PDF)Interactive HTML; static images with an extra package
InteractivityMinimal by defaultHover tooltips, zoom, pan and legend toggling built in
Quick APIdf.plot() in pandas, plus seaborn on topPlotly Express (px): one line per chart
Fine controlExcellent: every axis, tick and labelVery good via update_layout and update_traces
Best forReports, print, PDFs, academic figures, Power BI Python visualsExploration, notebooks, Streamlit and Dash apps, sharing HTML
Learning curveTwo interfaces (pyplot and object-oriented) can confuse beginnersPlotly 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.

Tip: Save report images as SVG or PDF (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

  1. Where will the chart live? A PDF, printed report or Word document points to Matplotlib. A browser, notebook or web app points to Plotly.
  2. Will people explore it? If readers need to hover for exact values or zoom into a date range, choose Plotly.
  3. 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.
  4. Are you building a dashboard app? Plotly integrates naturally with Dash and Streamlit; see Build Web Dashboards with Streamlit.
  5. 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.

AI shortcut: AI assistants are good at chart boilerplate. Try a prompt like: "Using Plotly Express, create a line chart from a pandas DataFrame df with columns Month, Region, Revenue: one line per region, dollar-formatted y-axis, a dashed horizontal line at the average revenue, and a clean white template. Then give me the Matplotlib version of the same chart." Comparing the two versions side by side is a fast way to learn both APIs.

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

Is Plotly The Better Matplotlib?by NeuralNine · Watch on YouTube ↗
Gráficos en Python con Matplotlib, Seaborn y Plotlyby Dattos.org · Watch on YouTube ↗Video in Spanish.

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.

Learning with the Academy?
Mark this lesson complete to track your rank progress.
Take the quiz