Matplotlib in Python is one of the most widely used tools for creating charts and scientific figures. It can produce simple line plots, category comparisons, scatter plots, histograms, pie charts, multi-panel figures, and publication-ready images. The library is especially valuable when you need precise control over a static chart.
This guide introduces Matplotlib through practical examples. You will install the package, learn the figure and axes model, customize labels and legends, create several chart types, work with Pandas, build subplots, and save high-quality output.
What is Matplotlib?
Matplotlib is an open-source plotting library. Its most commonly used interface is matplotlib.pyplot, conventionally imported as plt. The official Matplotlib user guide contains tutorials, explanations, and API references, while the official example gallery shows complete figures and their source code.
Matplotlib creates static charts by default. For browser-based interaction, hover labels, and built-in zoom controls, read our Plotly in Python guide. Many analysts use both libraries for different stages of a project.
Install Matplotlib
Create or activate a virtual environment, then install Matplotlib:
python -m pip install matplotlibCheck the installation:
import matplotlib
print(matplotlib.__version__)If a notebook or editor cannot import the package, verify that it uses the same Python interpreter in which pip installed Matplotlib.
Your first line chart
import matplotlib.pyplot as plt
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
sales = [120, 145, 138, 170, 190, 205]
plt.plot(months, sales)
plt.title("Monthly Sales")
plt.xlabel("Month")
plt.ylabel("Units")
plt.show()plt.plot() adds the line, and plt.show() displays the completed figure. A chart should include enough context for a reader to understand the variables and units without guessing.
Understand figures and axes
The object-oriented interface is more maintainable than relying entirely on global pyplot state:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(months, sales)
ax.set_title("Monthly Sales")
ax.set_xlabel("Month")
ax.set_ylabel("Units")
plt.show()The Figure is the whole output canvas. An Axes is one plotting area inside it. A figure can contain one axes or several axes arranged as subplots. Most advanced Matplotlib code works by calling methods on an axes object.
Add markers, line styles, and a grid
fig, ax = plt.subplots()
ax.plot(
months,
sales,
marker="o",
linestyle="--",
linewidth=2,
label="Sales",
)
ax.set_title("Monthly Sales")
ax.set_xlabel("Month")
ax.set_ylabel("Units")
ax.grid(True, alpha=0.3)
ax.legend()
plt.show()Styles should help distinguish data rather than decorate it excessively. A subtle grid can improve value estimation, while heavy grid lines can compete with the series.
Plot multiple series
online = [90, 100, 105, 125, 142, 150]
store = [60, 63, 58, 70, 74, 82]
fig, ax = plt.subplots()
ax.plot(months, online, marker="o", label="Online")
ax.plot(months, store, marker="s", label="Store")
ax.set_title("Sales by Channel")
ax.set_xlabel("Month")
ax.set_ylabel("Units")
ax.legend()
plt.show()Every series should have a meaningful label. If the chart contains too many lines, split it into smaller panels or summarize the data.
Create a bar chart
products = ["Laptop", "Mouse", "Keyboard", "Monitor"]
units = [35, 110, 78, 52]
fig, ax = plt.subplots()
ax.bar(products, units)
ax.set_title("Units Sold by Product")
ax.set_xlabel("Product")
ax.set_ylabel("Units")
plt.show()Bar charts compare categories. The numeric axis should normally begin at zero because bar length encodes magnitude.
Create grouped bars
import numpy as np
import matplotlib.pyplot as plt
products = ["Laptop", "Mouse", "Keyboard"]
q1 = [30, 95, 70]
q2 = [38, 112, 82]
positions = np.arange(len(products))
width = 0.35
fig, ax = plt.subplots()
ax.bar(positions - width / 2, q1, width, label="Q1")
ax.bar(positions + width / 2, q2, width, label="Q2")
ax.set_xticks(positions, products)
ax.set_ylabel("Units")
ax.set_title("Quarterly Product Sales")
ax.legend()
plt.show()NumPy creates consistent x-positions. The NumPy beginner guide explains arrays and vectorized numeric operations.
Create a scatter plot
study_hours = [2, 3, 4, 5, 6, 7, 8, 9]
scores = [55, 61, 65, 72, 78, 82, 88, 93]
fig, ax = plt.subplots()
ax.scatter(study_hours, scores)
ax.set_title("Study Hours and Scores")
ax.set_xlabel("Study hours")
ax.set_ylabel("Score")
plt.show()Scatter plots reveal relationships, clusters, and unusual observations. A visible pattern does not prove that one variable causes the other.
Create a histogram
A histogram summarizes the distribution of numerical values:
scores = [52, 61, 67, 71, 73, 74, 78, 82, 85, 85, 89, 92, 95]
fig, ax = plt.subplots()
ax.hist(scores, bins=5, edgecolor="black")
ax.set_title("Score Distribution")
ax.set_xlabel("Score")
ax.set_ylabel("Frequency")
plt.show()The number and boundaries of bins affect the apparent shape. Try several reasonable choices and avoid selecting bins merely to support a preferred conclusion.
Create a pie chart carefully
labels = ["Web", "Mobile", "Desktop"]
values = [55, 30, 15]
fig, ax = plt.subplots()
ax.pie(values, labels=labels, autopct="%1.0f%%", startangle=90)
ax.set_title("Traffic by Platform")
ax.axis("equal")
plt.show()Pie charts work best with a small number of clearly different proportions. For precise comparisons or many categories, a bar chart is usually easier to read.
Add annotations
fig, ax = plt.subplots()
ax.plot(months, sales, marker="o")
peak_index = sales.index(max(sales))
ax.annotate(
"Highest value",
xy=(months[peak_index], sales[peak_index]),
xytext=(-60, -35),
textcoords="offset points",
arrowprops={"arrowstyle": "->"},
)
ax.set_title("Monthly Sales")
plt.show()Annotations should identify important events or explain an unusual point. Too many labels create clutter.
Create subplots
Subplots compare related charts within one figure:
fig, axes = plt.subplots(1, 2, figsize=(11, 4))
axes[0].plot(months, sales, marker="o")
axes[0].set_title("Monthly Sales")
axes[0].set_ylabel("Units")
axes[1].bar(products, units)
axes[1].set_title("Sales by Product")
axes[1].tick_params(axis="x", rotation=30)
fig.tight_layout()
plt.show()figsize controls the overall dimensions in inches, and tight_layout() reduces overlapping labels. Each subplot is an independent axes object.
Work with Pandas
Pandas can plot through Matplotlib and also provides data-cleaning tools:
import pandas as pd
import matplotlib.pyplot as plt
data = pd.DataFrame({
"month": ["Jan", "Feb", "Mar", "Apr"],
"sales": [120, 145, 138, 170],
"expenses": [75, 83, 80, 95],
})
ax = data.plot(x="month", y=["sales", "expenses"], marker="o")
ax.set_title("Sales and Expenses")
ax.set_ylabel("Amount")
plt.show()The Pandas beginner guide covers DataFrames, filtering, missing values, grouping, and merging. Validate data types before plotting; numeric text and unparsed dates often lead to misleading axes.
Format numbers and dates
from matplotlib.ticker import StrMethodFormatter
fig, ax = plt.subplots()
ax.plot(months, [15000, 18000, 17000, 22000, 25000, 28000])
ax.yaxis.set_major_formatter(StrMethodFormatter("${x:,.0f}"))
ax.set_title("Monthly Revenue")
plt.show()For real date axes, use Python datetime objects or Pandas timestamps rather than preformatted strings. The formatter and locator APIs can then choose appropriate tick spacing.
Save a chart
Call savefig() before show():
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(months, sales, marker="o")
ax.set_title("Monthly Sales")
ax.set_xlabel("Month")
ax.set_ylabel("Units")
fig.savefig(
"monthly-sales.png",
dpi=300,
bbox_inches="tight",
)dpi=300 creates a high-resolution raster image, while bbox_inches="tight" reduces clipped labels and unnecessary margins. Matplotlib can also save PDF and SVG vector files by changing the extension.
Close figures in batch scripts
A long script that generates many charts should close each figure after saving it:
fig.savefig("chart.png", dpi=200, bbox_inches="tight")
plt.close(fig)This releases figure resources and prevents memory growth during batch processing.
Common beginner mistakes
- Forgetting
show(): interactive scripts may finish without displaying the figure. - Saving after
show(): some environments can clear or alter the current figure. Save first. - Mismatched x and y lengths: each series must contain compatible numbers of values.
- Unreadable labels: rotate long category labels or use a horizontal bar chart.
- Too many visual encodings: avoid combining unnecessary colors, markers, line styles, and annotations.
- Hidden state in pyplot: use explicit
figandaxobjects in reusable code. - Wrong environment: confirm the interpreter selected by the editor. The Academify guide to VS Code configuration explains interpreter selection.
Turn repeated chart code into a function
import matplotlib.pyplot as plt
def create_line_chart(x, y, title, output_path):
fig, ax = plt.subplots(figsize=(9, 5))
ax.plot(x, y, marker="o")
ax.set_title(title)
ax.grid(True, alpha=0.3)
fig.tight_layout()
fig.savefig(output_path, dpi=200)
plt.close(fig)Functions make chart generation consistent and testable. The Python docstrings guide shows how to document parameters, return values, and exceptions in reusable functions.
Matplotlib or Plotly?
Choose Matplotlib for static figures, printed reports, precise axes control, scientific conventions, and vector export. Choose Plotly when the audience needs interactive hover details, zooming, clickable legends, or browser-based sharing. A data pipeline can use Matplotlib for a PDF report and Plotly for an exploratory dashboard without conflict.
Conclusion
Matplotlib in Python provides a strong foundation for data visualization. Learn the figure and axes model, label every chart clearly, choose a chart type that matches the question, and save output with suitable dimensions and resolution. Once the basic patterns are familiar, the official gallery becomes an effective source of advanced examples and customization ideas.





