Matplotlib Basics

Difficulty: Intermediate

Matplotlib is the foundational plotting library in Python and serves as the backbone for most data visualization in the scientific Python ecosystem. Built on NumPy arrays, it provides a comprehensive API for creating static, animated, and interactive visualizations. The library follows a hierarchical structure where a Figure is the top-level container, Axes objects represent individual plots within that figure, and various artist objects (lines, text, patches) make up the visual elements drawn on those axes. Understanding this hierarchy is essential for creating well-structured and customizable plots.

The most common way to use Matplotlib is through its pyplot interface, imported as plt. This stateful interface tracks the 'current' figure and axes, allowing you to build up a plot step by step with function calls like plt.plot(), plt.title(), plt.xlabel(), and plt.show(). When you call plt.plot(x, y), Matplotlib creates a line connecting the (x, y) data points on the current axes. You can customize the line style, color, and marker using format strings like 'r--' for a red dashed line or 'bo' for blue circles. Every plot should include a descriptive title and axis labels so the viewer immediately understands what data is being presented.

The Figure and Axes objects give you finer-grained control over your plots. You can create them explicitly with fig, ax = plt.subplots(), which returns a Figure and an Axes object. The Axes object has methods like ax.set_title(), ax.set_xlabel(), and ax.set_ylabel() that mirror the pyplot functions but operate on a specific axes rather than the 'current' one. This object-oriented approach is preferred for complex visualizations because it makes the code more explicit and avoids ambiguity when working with multiple subplots.

Legends are critical when a plot contains multiple data series. By passing a label parameter to each plot call, such as plt.plot(x, y, label='Revenue'), and then calling plt.legend(), Matplotlib automatically generates a legend box that maps each label to its corresponding line style and color. You can control legend placement with the loc parameter, using values like 'upper right', 'lower left', or 'best' which lets Matplotlib choose the position that overlaps the least with data points.

While Matplotlib can render plots as images, in a browser-based Python environment like Pyodide the rendering capabilities may be limited. For learning and interview scenarios, it is more practical to focus on understanding the API, preparing data correctly, and knowing which configuration options to apply. The ability to describe how you would build a visualization and compute the underlying data is just as valuable as producing the image itself.

Code examples

Creating a basic line plot with labels

import matplotlib
matplotlib.use('Agg')  # Non-interactive backend
import matplotlib.pyplot as plt

# Data
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May']
revenue = [12000, 15000, 13500, 17000, 19500]

# Create figure and axes
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(months, revenue, marker='o', color='steelblue', linewidth=2)
ax.set_title('Monthly Revenue 2025')
ax.set_xlabel('Month')
ax.set_ylabel('Revenue ($)')

# Print what we configured
print(f"Title: {ax.get_title()}")
print(f"X-label: {ax.get_xlabel()}")
print(f"Y-label: {ax.get_ylabel()}")
print(f"Data points: {len(revenue)}")
print(f"Y range: ${min(revenue):,} - ${max(revenue):,}")
plt.close(fig)

We create a figure and axes using plt.subplots(), plot the data with markers and a custom color, then set the title and axis labels. The print statements verify the configuration. plt.close(fig) frees memory since we are not displaying interactively.

Multiple lines with a legend

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

quarters = ['Q1', 'Q2', 'Q3', 'Q4']
product_a = [200, 340, 290, 410]
product_b = [150, 280, 350, 320]

fig, ax = plt.subplots()
ax.plot(quarters, product_a, 'b-o', label='Product A')
ax.plot(quarters, product_b, 'r--s', label='Product B')
ax.set_title('Quarterly Sales Comparison')
ax.legend(loc='upper left')

# Verify legend entries
handles, labels = ax.get_legend_handles_labels()
print(f"Legend entries: {labels}")
print(f"Product A total: {sum(product_a)}")
print(f"Product B total: {sum(product_b)}")
print(f"Best quarter for A: {quarters[product_a.index(max(product_a))]} ({max(product_a)})")
print(f"Best quarter for B: {quarters[product_b.index(max(product_b))]} ({max(product_b)})")
plt.close(fig)

Two data series are plotted with different format strings: 'b-o' means blue solid line with circle markers, 'r--s' means red dashed line with square markers. The label parameter on each plot call feeds into the legend. We verify the legend entries and compute summary statistics.

Subplots for side-by-side comparison

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# Left subplot
days = list(range(1, 8))
temps = [22, 25, 23, 28, 30, 27, 24]
ax1.plot(days, temps, 'g-^')
ax1.set_title('Temperature (Week 1)')
ax1.set_xlabel('Day')
ax1.set_ylabel('Temp (C)')

# Right subplot
humidity = [65, 60, 70, 55, 50, 58, 63]
ax2.plot(days, humidity, 'm-d')
ax2.set_title('Humidity (Week 1)')
ax2.set_xlabel('Day')
ax2.set_ylabel('Humidity (%)')

print(f"Layout: 1 row x 2 columns")
print(f"Left plot: {ax1.get_title()}")
print(f"Right plot: {ax2.get_title()}")
print(f"Avg temp: {sum(temps)/len(temps):.1f}C")
print(f"Avg humidity: {sum(humidity)/len(humidity):.1f}%")
plt.close(fig)

plt.subplots(1, 2) creates a figure with two axes side by side. Each axes object is configured independently with its own title, labels, and data. This pattern is useful for comparing related but differently-scaled metrics.

Customizing line styles and colors

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

styles = {
    'solid': '-',
    'dashed': '--',
    'dotted': ':',
    'dash-dot': '-.'
}

markers = {
    'circle': 'o',
    'square': 's',
    'triangle': '^',
    'diamond': 'd',
    'star': '*'
}

colors = ['steelblue', 'coral', 'seagreen', 'goldenrod', 'mediumpurple']

print("Available line styles:")
for name, code in styles.items():
    print(f"  '{code}' = {name}")

print("\nCommon markers:")
for name, code in markers.items():
    print(f"  '{code}' = {name}")

print(f"\nNamed colors example: {colors}")
print(f"Format string 'r--o' = red, dashed, circle markers")
print(f"Format string 'b:s' = blue, dotted, square markers")

Matplotlib provides shorthand format strings that combine color, line style, and marker in a single string. For more control, you can pass keyword arguments like color='steelblue', linestyle='--', and marker='o' separately.

Key points

Concepts covered

plt.plot, plt.show, figure, axes, title, labels, legend