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.
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.
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.
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.
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.
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.
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