Box Plot Keywords¶
The ax.boxplot() method accepts numerous keyword arguments to control appearance and behavior.
Mental Model
Box plot keywords fall into three groups: data interpretation (vert, whis, showfliers), labeling (labels, positions), and styling (patch_artist, boxprops, medianprops). The most impactful is patch_artist=True, which switches boxes from outlines to filled patches, unlocking color customization.
Most Important Parameters
If you learn only four keywords, make it these:
whis— controls outlier definition (default 1.5×IQR; set to[5, 95]for percentile-based whiskers)showfliers— toggle outlier dots on/off (hide them to reduce noise in dense data)notch— adds a confidence interval notch around the median (non-overlapping notches suggest different medians)patch_artist— switches boxes to filled patches (required for color customization)
Labels¶
The labels keyword assigns names to each box on the x-axis.
1. Basic Labels¶
```python import matplotlib.pyplot as plt import numpy as np
np.random.seed(42) data_a = np.random.normal(100, 10, 200) data_b = np.random.normal(90, 20, 200) data_c = np.random.normal(110, 15, 200)
fig, ax = plt.subplots() ax.boxplot([data_a, data_b, data_c], labels=['Group A', 'Group B', 'Group C']) plt.show() ```
2. LaTeX Labels¶
python
ax.boxplot([data_a, data_b, data_c],
labels=[r'$10^4$', r'$5 \cdot 10^4$', r'$10^5$'])
3. Numeric Labels¶
python
ax.boxplot([data_a, data_b, data_c], labels=['N=100', 'N=500', 'N=1000'])
Widths¶
The widths keyword controls the width of each box.
1. Uniform Width¶
python
ax.boxplot([data_a, data_b, data_c], widths=0.5) # All boxes same width
2. Variable Widths¶
python
ax.boxplot([data_a, data_b, data_c], widths=[0.2, 0.4, 0.6])
3. Proportional to Sample Size¶
python
sizes = [100, 500, 1000]
widths = [np.sqrt(s) / np.sqrt(max(sizes)) * 0.8 for s in sizes]
ax.boxplot([data_a, data_b, data_c], widths=widths)
Orientation¶
The vert keyword controls vertical or horizontal orientation.
1. Vertical (Default)¶
python
ax.boxplot(data, vert=True)
2. Horizontal¶
python
fig, ax = plt.subplots()
ax.boxplot([data_a, data_b, data_c], vert=False)
ax.set_yticklabels(['A', 'B', 'C'])
ax.set_xlabel('Value')
plt.show()
3. Use Case¶
Horizontal orientation works well when labels are long or when comparing many groups.
Notch¶
The notch keyword adds confidence interval notches around the median.
1. Enable Notches¶
python
ax.boxplot(data, notch=True)
2. Interpretation¶
Non-overlapping notches between two boxes suggest the medians differ significantly at approximately the 95% confidence level.
3. Notch Calculation¶
```python
Notch extent approximation¶
notch_extent = 1.57 * IQR / np.sqrt(n) ```
Patch Artist¶
The patch_artist keyword enables filled boxes for color customization.
1. Enable Patch Artist¶
python
bp = ax.boxplot(data, patch_artist=True)
2. Access Box Patches¶
python
for patch in bp['boxes']:
patch.set_facecolor('lightblue')
3. Required for Fill Colors¶
Without patch_artist=True, boxes are drawn as lines only and cannot be filled.
Show Statistics¶
Keywords control which statistical markers appear.
1. Show Mean¶
python
ax.boxplot(data, showmeans=True)
2. Show Fliers (Outliers)¶
python
ax.boxplot(data, showfliers=True) # Default
ax.boxplot(data, showfliers=False) # Hide outliers
3. Mean Line Instead of Point¶
python
ax.boxplot(data, showmeans=True, meanline=True)
Whisker Range¶
The whis keyword controls whisker extent.
1. Default (1.5 IQR)¶
python
ax.boxplot(data, whis=1.5)
2. Custom Multiplier¶
python
ax.boxplot(data, whis=2.0) # Fewer outliers shown
3. Percentile Range¶
python
ax.boxplot(data, whis=[5, 95]) # Whiskers at 5th and 95th percentiles
Exercises¶
Exercise 1.
Create a box plot of three datasets with the following customizations: notch=True, patch_artist=True, showmeans=True with a diamond marker. Use different face colors for each box and set medianprops to display a red line.
Solution to Exercise 1
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data = [np.random.randn(100) + i for i in range(3)]
fig, ax = plt.subplots(figsize=(8, 5))
bp = ax.boxplot(data, notch=True, patch_artist=True, showmeans=True,
meanprops=dict(marker='D', markerfacecolor='gold', markersize=8),
medianprops=dict(color='red', linewidth=2))
colors = ['lightblue', 'lightcoral', 'lightgreen']
for patch, color in zip(bp['boxes'], colors):
patch.set_facecolor(color)
ax.set_xticklabels(['Group 1', 'Group 2', 'Group 3'])
ax.set_title('Notched Box Plot with Means')
plt.show()
Exercise 2.
Create a box plot using showfliers=False to hide outliers, and instead overlay individual data points using ax.scatter with jitter (small random horizontal offsets). Use 200 samples from a standard normal distribution across 4 groups.
Solution to Exercise 2
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data = [np.random.randn(200) for _ in range(4)]
fig, ax = plt.subplots(figsize=(8, 5))
ax.boxplot(data, showfliers=False, patch_artist=True,
boxprops=dict(facecolor='lightyellow'))
for i, d in enumerate(data, 1):
jitter = np.random.uniform(-0.15, 0.15, len(d))
ax.scatter(np.full_like(d, i) + jitter, d, alpha=0.3, s=10, color='steelblue')
ax.set_xticklabels(['A', 'B', 'C', 'D'])
ax.set_title('Box Plot with Jittered Data Points')
plt.show()
Exercise 3.
Create a box plot with widths=[0.3, 0.5, 0.7, 0.9] for four datasets to show how box width affects visual perception. Use patch_artist=True with graduated blue colors (light to dark). Set whiskerprops, capprops, and flierprops to customize every visible component.
Solution to Exercise 3
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data = [np.random.randn(100) * (i + 1) for i in range(4)]
fig, ax = plt.subplots(figsize=(8, 5))
bp = ax.boxplot(data, widths=[0.3, 0.5, 0.7, 0.9], patch_artist=True,
whiskerprops=dict(color='navy', linewidth=1.5),
capprops=dict(color='navy', linewidth=2),
flierprops=dict(marker='o', markerfacecolor='red', markersize=4))
blues = ['#c6dbef', '#6baed6', '#2171b5', '#08306b']
for patch, color in zip(bp['boxes'], blues):
patch.set_facecolor(color)
ax.set_xticklabels(['Narrow', 'Medium', 'Wide', 'Widest'])
ax.set_title('Variable Width Box Plots')
plt.show()