Matplotlib Chart Types · Examples
Data

Matplotlib Chart Types Examples

Short, runnable programs that show matplotlib chart types in action. Read the explanation, press Run, then change the code and try your own ideas. New to the topic? Start with the Matplotlib Chart Types lesson.

1Compare two groups with density histograms

The old checkout has 14 customers and the new one has 22, so raw counts would not be comparable. density=True rescales both histograms, alpha makes them see-through, and both use the same bins so the bars line up.

Compare two groups with density histograms
import numpy as np
import matplotlib.pyplot as plt

old_site = [34, 41, 38, 52, 47, 39, 44, 58, 36, 49, 42, 55, 40, 46]
new_site = [28, 31, 26, 35, 30, 41, 29, 33, 27, 36, 32, 30, 34, 29, 38, 31, 25, 33, 28, 37, 30, 32]

fig, ax = plt.subplots(figsize=(6, 3.2))
bins = range(20, 65, 5)
ax.hist(old_site, bins=bins, density=True, alpha=0.6, label="old checkout")
ax.hist(new_site, bins=bins, density=True, alpha=0.6, label="new checkout")
ax.set_xlabel("Seconds to complete checkout")
ax.set_ylabel("Share of customers (density)")
ax.legend()
print("Mean old:", round(np.mean(old_site), 1), "| mean new:", round(np.mean(new_site), 1))
plt.show()
Expected outputMean old: 44.4 | mean new: 31.6

2Sorted horizontal bars with one highlighted

Sorting from smallest to largest puts the biggest bar at the top of a horizontal chart. One accent colour for the region you are talking about and grey for the rest guides the eye, and bar_label prints the values at the bar ends.

Sorted horizontal bars with one highlighted
import matplotlib.pyplot as plt

sales = {"North": 120, "South": 95, "East": 143, "West": 88, "Central": 110}
ranked = sorted(sales.items(), key=lambda item: item[1])
regions = [name for name, total in ranked]
totals = [total for name, total in ranked]
colors = ["tab:blue" if name == "East" else "lightgray" for name in regions]

fig, ax = plt.subplots(figsize=(6, 3))
bars = ax.barh(regions, totals, color=colors)
ax.bar_label(bars)
ax.set_xlabel("Units sold")
ax.set_title("East leads the regions")
print("Top region:", regions[-1], totals[-1])
plt.show()
Expected outputTop region: East 143

3Stacked area chart: where does the traffic come from?

stackplot draws each source on top of the previous one, so the top edge is the total and each band shows one source. The legend is placed in an empty corner with loc.

Stacked area chart: where does the traffic come from?
import matplotlib.pyplot as plt

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
search = [300, 320, 350, 380, 420, 450]
social = [120, 150, 140, 190, 210, 240]
direct = [200, 190, 210, 205, 215, 220]

fig, ax = plt.subplots(figsize=(6, 3.2))
ax.stackplot(months, search, social, direct, labels=["Search", "Social", "Direct"])
ax.set_ylabel("Visitors")
ax.set_title("Visitors by source")
ax.legend(loc="upper left")
totals = [a + b + c for a, b, c in zip(search, social, direct)]
print("Total visitors:", totals)
plt.show()
Expected outputTotal visitors: [620, 660, 700, 775, 845, 910]

4Box plot: same median, different spread

All three couriers have a median of 24 minutes, so an average-only bar chart would call them equal. The boxes show that Ana is unpredictable and Raj has one terrible delivery (the dot), while Li is very consistent. set_xticks puts the names under the boxes, which sit at positions 1, 2 and 3.

Box plot: same median, different spread
import numpy as np
import matplotlib.pyplot as plt

times = {
    "Ana": [16, 19, 21, 22, 24, 26, 28, 30, 33],
    "Raj": [18, 20, 22, 23, 24, 25, 26, 27, 52],
    "Li": [22, 23, 23, 24, 24, 25, 25, 26, 27],
}

fig, ax = plt.subplots(figsize=(6, 3.2))
ax.boxplot(list(times.values()))
ax.set_xticks([1, 2, 3], list(times))
ax.set_ylabel("Delivery time (minutes)")
ax.set_title("Same median, different spread")
for name, values in times.items():
    print(name, "median", np.median(values), "range", max(values) - min(values))
plt.show()
Expected outputAna median 24.0 range 17
Raj median 24.0 range 34
Li median 24.0 range 5

5Annotated correlation heatmap

np.corrcoef turns four rows of measurements into a 4 x 4 grid of correlations. The RdBu scale with vmin=-1 and vmax=1 puts zero in the pale middle, red and blue mean opposite directions, and white text keeps the dark cells readable.

Annotated correlation heatmap
import numpy as np
import matplotlib.pyplot as plt

habits = ["Sleep", "Exercise", "Screen", "Score"]
data = np.array([
    [6.0, 7.5, 5.5, 8.0, 7.0, 6.5, 9.0, 5.0],
    [2, 3, 1, 4, 2, 0, 3, 2],
    [4, 2, 6, 3, 5, 3, 1, 5],
    [62, 70, 52, 76, 74, 58, 81, 60],
])
corr = np.corrcoef(data)

fig, ax = plt.subplots(figsize=(5, 4))
image = ax.imshow(corr, cmap="RdBu", vmin=-1, vmax=1)
fig.colorbar(image, ax=ax)
ax.set_xticks(range(4), labels=habits)
ax.set_yticks(range(4), labels=habits)
for i in range(4):
    for j in range(4):
        shade = "white" if abs(corr[i, j]) > 0.7 else "black"
        ax.text(j, i, f"{corr[i, j]:.2f}", ha="center", va="center", color=shade)
print("Sleep vs score:", round(corr[0, 3], 2))
print("Screen vs score:", round(corr[2, 3], 2))
plt.show()
Expected outputSleep vs score: 0.89
Screen vs score: -0.66

6Two units on one chart: bars, a line and a second axis

Rainfall (mm) and temperature (degrees) cannot share one y-axis, so twinx() adds a second one on the right. Each axis label takes the colour of its series, a dotted line marks 10 degrees, and annotate points at the first month above it.

Two units on one chart: bars, a line and a second axis
import matplotlib.pyplot as plt

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
rain = [78, 62, 55, 48, 52, 45]
temp = [4, 5, 8, 11, 15, 18]

fig, ax = plt.subplots(figsize=(6, 3.4))
ax.bar(months, rain, color="tab:blue", alpha=0.35)
ax.set_ylabel("Rain (mm)", color="tab:blue")
warm = ax.twinx()
warm.plot(months, temp, color="tab:red", marker="o")
warm.set_ylabel("Temperature (C)", color="tab:red")
warm.axhline(10, color="gray", linestyle=":")
warm.annotate("first month above 10 C", xy=("Apr", 11), xytext=("Jan", 14),
              arrowprops={"arrowstyle": "->"})
ax.set_title("Wetter when colder")
print("Rainiest:", months[rain.index(max(rain))], "| warmest:", months[temp.index(max(temp))])
plt.show()
Expected outputRainiest: Jan | warmest: Jun

Practise next

Matplotlib Chart Types exercises → Back to the lesson

NumPy Math and Broadcasting examplesPandas Basics examplespandas groupby and Pivot Tables examplesMatplotlib Basics examples