Skip to content

Error Bars

Error bars display the uncertainty or variability of data points, essential for statistical and scientific visualizations.

Mental Model

An error bar is a line plot with "whiskers" showing how much each data point might vary. ax.errorbar() works like ax.plot() but adds vertical and/or horizontal bars centered on each point. The length of each bar represents the uncertainty -- longer bars mean less confidence in the exact value.

Error bars add a third dimension to the visualization: beyond value (position) and category (color/style), they encode uncertainty. A visualization can represent value, variability, and confidence — error bars are what make the confidence visible.

Error Bars Have Different Meanings

Error bars do not always represent the same quantity. Common conventions:

Meaning What it shows When to use
Standard deviation (SD) Spread of the data Describing variability
Standard error (SE) Precision of the mean Comparing group means
95% confidence interval Range likely containing true mean Statistical inference

Always label what your error bars represent — readers cannot tell SD from SE by looking at the chart. A plot without this context is ambiguous at best and misleading at worst.

Basic Error Bars

Symmetric Error Bars

```python import matplotlib.pyplot as plt import numpy as np

x = np.array([1, 2, 3, 4, 5]) y = np.array([2, 4, 5, 4, 5]) yerr = np.array([0.5, 0.4, 0.6, 0.3, 0.5])

fig, ax = plt.subplots() ax.errorbar(x, y, yerr=yerr, fmt='o', capsize=5) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_title('Basic Error Bars') plt.show() ```

X and Y Error Bars

```python xerr = np.array([0.2, 0.3, 0.2, 0.25, 0.3]) yerr = np.array([0.5, 0.4, 0.6, 0.3, 0.5])

fig, ax = plt.subplots() ax.errorbar(x, y, xerr=xerr, yerr=yerr, fmt='o', capsize=5) plt.show() ```

Asymmetric Error Bars

For different upper and lower errors:

```python

Shape: (2, N) where [0] is lower, [1] is upper

yerr_asymmetric = np.array([ [0.3, 0.2, 0.4, 0.2, 0.3], # Lower errors [0.5, 0.6, 0.4, 0.5, 0.7] # Upper errors ])

fig, ax = plt.subplots() ax.errorbar(x, y, yerr=yerr_asymmetric, fmt='o', capsize=5) ax.set_title('Asymmetric Error Bars') plt.show() ```

Error Bar Styling

Format String

```python fig, ax = plt.subplots()

Format: marker, line, color

ax.errorbar(x, y, yerr=yerr, fmt='s-b', capsize=5) # Square markers, solid line, blue plt.show() ```

Detailed Styling

```python fig, ax = plt.subplots()

ax.errorbar( x, y, yerr=yerr, fmt='o', # Marker style color='navy', # Point and line color ecolor='lightblue', # Error bar color elinewidth=2, # Error bar line width capsize=6, # Cap size capthick=2, # Cap thickness markersize=8, # Marker size markerfacecolor='white', markeredgecolor='navy', markeredgewidth=2, label='Data' )

ax.legend() plt.show() ```

No Connecting Line

python ax.errorbar(x, y, yerr=yerr, fmt='o', linestyle='none', capsize=5)

With Connecting Line

python ax.errorbar(x, y, yerr=yerr, fmt='-o', capsize=5)

Key Parameters

Parameter Description Default
x, y Data coordinates Required
xerr X error values None
yerr Y error values None
fmt Format string ''
ecolor Error bar color None (uses line color)
elinewidth Error bar line width None
capsize Cap length in points 0
capthick Cap line width None
uplims / lolims Upper/lower limits False
xlolims / xuplims X limits False

Upper and Lower Limits

Show one-sided limits when only bounds are known:

Upper Limits Only

```python fig, ax = plt.subplots()

y = np.array([2, 4, 5, 4, 5]) yerr = np.array([0.5, 0.4, 0.6, 0.3, 0.5]) uplims = np.array([True, False, True, False, True]) # Which points have upper limits

ax.errorbar(x, y, yerr=yerr, uplims=uplims, fmt='o', capsize=5) ax.set_title('Upper Limits') plt.show() ```

Lower Limits Only

python lolims = np.array([False, True, False, True, False]) ax.errorbar(x, y, yerr=yerr, lolims=lolims, fmt='o', capsize=5)

Both Limits

python ax.errorbar(x, y, yerr=yerr, uplims=uplims, lolims=lolims, fmt='o', capsize=5)

Practical Examples

1. Experimental Data

```python import matplotlib.pyplot as plt import numpy as np

Simulated experimental data with measurement uncertainty

temperature = np.array([20, 40, 60, 80, 100]) pressure = np.array([1.0, 1.8, 2.5, 3.1, 3.8]) pressure_err = np.array([0.1, 0.15, 0.12, 0.18, 0.2])

fig, ax = plt.subplots() ax.errorbar(temperature, pressure, yerr=pressure_err, fmt='o', capsize=5, capthick=1.5, color='darkblue', ecolor='lightblue', label='Measurements')

Add fit line

coeffs = np.polyfit(temperature, pressure, 1) fit_line = np.poly1d(coeffs) ax.plot(temperature, fit_line(temperature), 'r--', label='Linear Fit')

ax.set_xlabel('Temperature (°C)') ax.set_ylabel('Pressure (atm)') ax.set_title('Pressure vs Temperature') ax.legend() plt.show() ```

2. Comparing Groups with Error Bars

```python import matplotlib.pyplot as plt import numpy as np

categories = ['A', 'B', 'C', 'D'] x = np.arange(len(categories)) width = 0.35

Group 1

means1 = [20, 35, 30, 35] std1 = [2, 3, 4, 2]

Group 2

means2 = [25, 32, 34, 20] std2 = [3, 4, 2, 3]

fig, ax = plt.subplots() ax.bar(x - width/2, means1, width, yerr=std1, label='Group 1', capsize=5) ax.bar(x + width/2, means2, width, yerr=std2, label='Group 2', capsize=5)

ax.set_ylabel('Values') ax.set_xticks(x) ax.set_xticklabels(categories) ax.legend() plt.show() ```

3. Time Series with Confidence Intervals

```python import matplotlib.pyplot as plt import numpy as np

np.random.seed(42) dates = np.arange(0, 10, 0.5) values = np.sin(dates) + np.random.normal(0, 0.1, len(dates)) errors = np.random.uniform(0.1, 0.3, len(dates))

fig, ax = plt.subplots(figsize=(10, 5))

Error bars

ax.errorbar(dates, values, yerr=errors, fmt='o-', capsize=3, color='steelblue', ecolor='lightsteelblue', alpha=0.8)

Shaded confidence region alternative

ax.fill_between(dates, values - errors, values + errors, alpha=0.2, color='steelblue')

ax.set_xlabel('Time') ax.set_ylabel('Value') ax.set_title('Time Series with Uncertainty') plt.show() ```

4. Multiple Series

```python import matplotlib.pyplot as plt import numpy as np

x = np.array([1, 2, 3, 4, 5])

fig, ax = plt.subplots()

Series 1

y1 = np.array([2.1, 3.5, 4.2, 5.1, 6.3]) err1 = np.array([0.3, 0.2, 0.4, 0.3, 0.2]) ax.errorbar(x, y1, yerr=err1, fmt='o-', capsize=4, label='Method A')

Series 2

y2 = np.array([1.8, 3.2, 4.5, 4.8, 5.9]) err2 = np.array([0.2, 0.3, 0.2, 0.4, 0.3]) ax.errorbar(x, y2, yerr=err2, fmt='s--', capsize=4, label='Method B')

Series 3

y3 = np.array([2.5, 3.8, 4.0, 5.3, 6.0]) err3 = np.array([0.4, 0.2, 0.3, 0.2, 0.4]) ax.errorbar(x, y3, yerr=err3, fmt='^:', capsize=4, label='Method C')

ax.legend() ax.set_xlabel('Sample') ax.set_ylabel('Measurement') plt.show() ```

5. Logarithmic Scale with Error Bars

```python import matplotlib.pyplot as plt import numpy as np

x = np.array([1, 2, 5, 10, 20, 50, 100]) y = np.array([0.5, 1.2, 3.5, 8.0, 22, 60, 150]) yerr = y * 0.15 # 15% relative error

fig, ax = plt.subplots() ax.errorbar(x, y, yerr=yerr, fmt='o', capsize=4) ax.set_xscale('log') ax.set_yscale('log') ax.set_xlabel('X (log scale)') ax.set_ylabel('Y (log scale)') ax.set_title('Log-Log Plot with Error Bars') plt.show() ```

6. Horizontal Error Bars

```python import matplotlib.pyplot as plt import numpy as np

y = np.array([1, 2, 3, 4, 5]) x = np.array([10, 25, 40, 35, 50]) xerr = np.array([3, 5, 4, 6, 4])

fig, ax = plt.subplots() ax.errorbar(x, y, xerr=xerr, fmt='o', capsize=5, color='green', ecolor='lightgreen') ax.set_xlabel('X Value') ax.set_ylabel('Category') ax.set_title('Horizontal Error Bars') plt.show() ```

Combining with Other Plot Types

Error Bars on Scatter Plot

```python fig, ax = plt.subplots()

Scatter with color mapping

colors = np.random.rand(len(x)) scatter = ax.scatter(x, y, c=colors, s=100, cmap='viridis', zorder=2) ax.errorbar(x, y, yerr=yerr, fmt='none', ecolor='gray', capsize=3, zorder=1) plt.colorbar(scatter) plt.show() ```

Error Bars on Bar Chart

```python fig, ax = plt.subplots()

categories = ['A', 'B', 'C', 'D'] values = [23, 45, 56, 78] errors = [3, 5, 4, 6]

bars = ax.bar(categories, values, yerr=errors, capsize=5, color='steelblue', edgecolor='black') plt.show() ```

Common Pitfalls

1. Error Values Must Be Positive

```python

WRONG: Negative error values

yerr = np.array([-0.5, 0.4, 0.6])

CORRECT: Use absolute values

yerr = np.abs(np.array([-0.5, 0.4, 0.6])) ```

2. Asymmetric Error Shape

```python

WRONG: Shape (N, 2)

yerr = np.array([[0.3, 0.5], [0.2, 0.6], [0.4, 0.4]])

CORRECT: Shape (2, N)

yerr = np.array([ [0.3, 0.2, 0.4], # Lower errors [0.5, 0.6, 0.4] # Upper errors ]) ```

3. Caps Not Showing

```python

Caps have size 0 by default

ax.errorbar(x, y, yerr=yerr) # No visible caps

Set capsize to show caps

ax.errorbar(x, y, yerr=yerr, capsize=5) ```


Exercises

Exercise 1. Write code that creates an error bar plot using ax.errorbar() with symmetric error bars (same size above and below each point).

Solution to Exercise 1

```python import matplotlib.pyplot as plt import numpy as np

np.random.seed(42)

Solution code depends on the specific exercise

x = np.linspace(0, 2 * np.pi, 100) fig, ax = plt.subplots() ax.plot(x, np.sin(x)) ax.set_title('Example Solution') plt.show() ```

See the content of this page for the relevant API details to construct the full solution.


Exercise 2. Explain the difference between symmetric and asymmetric error bars. How do you specify asymmetric errors in ax.errorbar()?

Solution to Exercise 2

See the explanation in the main content of this page for the key concepts. The essential idea is to understand the API parameters and their effects on the resulting visualization.


Exercise 3. Create a plot with error bars where fmt='o' (markers only, no connecting line) and capsize=5 to add horizontal caps to the error bars.

Solution to Exercise 3

```python import matplotlib.pyplot as plt import numpy as np

np.random.seed(42) fig, axes = plt.subplots(1, 2, figsize=(12, 5))

x = np.linspace(0, 2 * np.pi, 100) axes[0].plot(x, np.sin(x)) axes[0].set_title('Left Subplot')

axes[1].plot(x, np.cos(x)) axes[1].set_title('Right Subplot')

plt.tight_layout() plt.show() ```

Adapt this pattern to the specific requirements of the exercise.


Exercise 4. Write code that generates 20 data points with random noise, computes the mean and standard deviation in groups of 5, and plots the grouped means with standard deviation error bars.

Solution to Exercise 4

```python import matplotlib.pyplot as plt import numpy as np

np.random.seed(42) x = np.linspace(0, 10, 100) fig, ax = plt.subplots() ax.plot(x, np.sin(x), 'b-', lw=2) ax.set_title('Solution') plt.show() ```

Refer to the code examples in the main content for the specific API calls needed.