Python has two common routes for box plots: matplotlib for direct control, and seaborn for DataFrame-friendly grouped charts. Here's how to use both without hiding the statistical defaults.
Matplotlib box plot
The fastest way to plot a single distribution:
import matplotlib.pyplot as plt
data = [62, 65, 68, 71, 73, 75, 78, 81, 85, 87, 95, 42]
fig, ax = plt.subplots(figsize=(6, 5))
ax.boxplot(data)
ax.set_ylabel("Score")
ax.set_title("Test Score Distribution")
plt.tight_layout()
plt.savefig("boxplot.png", dpi=150)
plt.show()
ax.boxplot() uses the standard Tukey-style 1.5×IQR whisker rule by default. Points beyond the whiskers are plotted as flier markers automatically.
Grouped box plots with matplotlib
Compare multiple groups side by side:
import matplotlib.pyplot as plt
class_a = [65, 70, 72, 75, 78, 80, 82, 85]
class_b = [55, 62, 68, 70, 74, 76, 85, 92]
class_c = [70, 72, 74, 76, 78, 80, 82, 84]
fig, ax = plt.subplots(figsize=(8, 5))
ax.boxplot([class_a, class_b, class_c],
labels=["Class A", "Class B", "Class C"])
ax.set_ylabel("Score")
ax.set_title("Score Distribution by Class")
plt.tight_layout()
plt.show()
Seaborn box plot (recommended)
Seaborn produces publication-ready plots with less code and handles pandas DataFrames natively:
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({
"score": [65, 70, 72, 75, 78, 80, 82, 85,
55, 62, 68, 70, 74, 76, 85, 92,
70, 72, 74, 76, 78, 80, 82, 84],
"class": (["Class A"] * 8 + ["Class B"] * 8 + ["Class C"] * 8)
})
fig, ax = plt.subplots(figsize=(8, 5))
sns.boxplot(data=df, x="class", y="score", ax=ax)
ax.set_title("Score Distribution by Class")
plt.tight_layout()
plt.show()
Customizing the box plot
- Change whisker length —
whis=parameter. Default is 1.5. Usewhis=2.0for a wider range before marking outliers. - Hide outliers —
showfliers=Falsehides flier markers in matplotlib and seaborn. Only do this for presentation reasons; don't remove the values from the analysis unless you have a defensible rule. - Fill box with color —
patch_artist=Truein matplotlib, orpalette=in seaborn. - Show the mean —
showmeans=Truein matplotlib adds a mean marker (triangle by default). - Notched box plot —
notch=Trueadds notches around the median. Overlapping notches indicate medians are not significantly different.
Seaborn with color palette
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
# Using the same df from above
fig, ax = plt.subplots(figsize=(8, 5))
sns.boxplot(
data=df,
x="class",
y="score",
palette="Set2",
linewidth=1.5,
ax=ax
)
sns.despine()
ax.set_title("Score Distribution by Class")
plt.tight_layout()
plt.show()
sns.despine() removes the top and right spines for a cleaner look.
Adding individual data points (strip plot)
Showing all data points alongside the box plot gives full transparency:
fig, ax = plt.subplots(figsize=(8, 5))
sns.boxplot(data=df, x="class", y="score", palette="Set2", ax=ax)
sns.stripplot(data=df, x="class", y="score",
color="black", alpha=0.4, size=4, jitter=True, ax=ax)
plt.tight_layout()
plt.show()
This combination — box plot + strip plot — is increasingly standard in scientific publications where readers expect to see the raw data.
FAQ
Which library should I use — matplotlib or seaborn?
Start with seaborn. It handles DataFrames natively, has better defaults, and produces publication-quality charts with minimal code. Switch to matplotlib when you need precise control over specific visual elements that seaborn doesn't expose.
How do I change the outlier marker style in matplotlib?
Pass flierprops as a dict: ax.boxplot(data, flierprops=dict(marker='o', markerfacecolor='red', markersize=6)). The marker, markerfacecolor, markeredgecolor, and markersize keys control the outlier appearance.
Can I make a horizontal box plot?
In current matplotlib, use orientation="horizontal"; older examples often use vert=False, which is being phased out. In seaborn, swap x and y: sns.boxplot(data=df, y="class", x="score").
How do I export the chart as SVG?
Use plt.savefig("boxplot.svg"). Matplotlib natively supports SVG export — just change the file extension. For vector-quality publication figures, SVG or PDF are both good choices: plt.savefig("boxplot.pdf").
References
How this guide is reviewed
This guide is maintained by the ChartsMakers Editorial Team and reviewed for statistical accuracy, product behavior, and clarity. Sources used for factual checks are listed in the References section. See our editorial policy.