Bar charts with error bars are useful in engineering to show the confidence or precision in a set of measurements or calculated values. Bar charts without error bars give the illusion that a measured or calculated value is known to high precision or high confidence. In this post, we will build a bar plot using Python and atplotlib. The plot will show the coefficient of thermal expansion (CTE) of three different materials based on a small data set. Then we'll add error bars to this chart based on the standard deviation of the data.

A bar chart with error bars is shown below. Note the labels on the x-axis and the error bars at the top of each bar.

plot with error bars

In order to build this plot, we need a couple of things:

Asset Description
Python (version 3.6) Run the program
Anaconda Prompt create the virtual environment and install packages
numpy calculate the mean and standard deviation
matplotlib build the plot
data set data to plot

Before you can build the plot, make sure you have the Anaconda Distribution of Python installed on your computer. See installing Anaconda on Windows for installation instructions.

To get going, we'll use the Anaconda Prompt to create a new virtual environment. Select Anaconda Prompt from the Windows Start Menu. (If using OSX or Linux, the terminal could also be used)

conda prompt on windows start menu

Once you have the Anaconda Prompt open, type the following command to create a new virtual environment:

conda create -n errorbars

Next, to activate our new (errorbars) virtual environment, type the following into the Anaconda Prompt

conda activate errorbars

Now that the errorbars virtual environment is active, you should see (errorbars) in parenthesis before the Anaconda Prompt.

Now we'll install matplotlib and numpy using conda. (pip will work to install these packages as well) You can write both package names on the same line or use two different conda install lines.

conda install matplotlib numpy

To confirm our (errorbars) virtual environment has matplotlib and numpy installed, run the command:

conda list

Now let's create a new Python script called errorbars.py. At the top of the script we need to import numpy and matplotlib.

# errorbars.py

import numpy as np
import matplotlib.pyplot as plt

Next, we need to read in our data. The chart below shows the measured coefficient of thermal expansion (CTE) of three metals: Aluminum, Copper and Steel. The units for coefficient of thermal expansion is per degrees C ( / °C)

Coefficient of thermal expansion of three metals (units: / °C)

Sample Aluminum Copper Steel
1 6.4e-5 4.5e-5 3.3e-5
2 3.01e-5 1.97e-5 1.21e-5
3 2.36e-5 1.6e-5 0.9e-5
4 3.0e-5 1.97e-5 1.2e-5
5 7.0e-5 4.0e-5 1.3e-5
6 4.5e-5 2.4e-5 1.6e-5
7 3.8e-5 1.9e-5 1.4e-5
8 4.2e-5 2.41e-5 1.58e-5
9 2.62e-5 1.85e-5 1.32e-5
10 3.6e-5 3.3e-5 2.1e-5

We'll put this data into three different numpy arrays, one array for each metal. Notice the syntax np.array([ ... ]) has a parenthesis ( followed by a square bracket [. We are passing a Python list, [ denoted with square brackets ] into the numpy array function (argument enclosed in parenthesis).

# Enter raw data
aluminum = np.array([6.4e-5 , 3.01e-5 , 2.36e-5, 3.0e-5, 7.0e-5, 4.5e-5, 3.8e-5, 4.2e-5, 2.62e-5, 3.6e-5])
copper = np.array([4.5e-5 , 1.97e-5 , 1.6e-5, 1.97e-5, 4.0e-5, 2.4e-5, 1.9e-5, 2.41e-5 , 1.85e-5, 3.3e-5 ])
steel = np.array([3.3e-5 , 1.2e-5 , 0.9e-5, 1.2e-5, 1.3e-5, 1.6e-5, 1.4e-5, 1.58e-5, 1.32e-5 , 2.1e-5])

Now we need to calculate the mean (or average) for each of the three material's CTE using numpy's np.mean() function. The means will be the height of each bar in our chart.

# Calculate the average
Aluminum_mean = np.mean(aluminum)
Copper_mean = np.mean(copper)
Steel_mean = np.mean(steel)

Next we'll calculate the standard deviation for each metal using numpy's np.std() function. On the plot, we will use the standard deviation as the height of our error bars. The positive error will be show as +1 standard deviation above the mean, and the negative error will be shown as -1 standard deviation below the mean.

# Calculate the standard deviation
aluminum_std = np.std(aluminum)
copper_std = np.std(copper)
steel_std = np.std(steel)

There are a couple more things needed to build the plot. We need the names of the metals to go along our x-axis, one name below each bar. We'll assign the metal names as list of strings in a variable called materials. We also need a variable that contains the means of the coefficients of thermal expansion, the data we are going to plot. We'll put these into a Python list called CTEs. Our standard deviations will be used for the height of the error bars. The standard deviations will go together in a list called error.

Let's code all of these Python list into our errorbars.py script.

# Create lists for the plot
materials = ['Aluminum', 'Copper', 'Steel']
x_pos = np.arange(len(materials))
CTEs = [aluminum_mean, copper_mean, steel_mean]
error = [aluminum_std, copper_std, steel_std]

OK. Now it's time to build the plot. We are going to build a bar chart with three different bars, one bar for each material: Aluminum, Copper and Steel.

First we will create a figure object called fig and an axis object in that figure called ax using matplotlib's plt.subplots() function. Everything in our plot will be added to the ax (axis) object. Next we put a bar chart on our ax (axis) with the ax.bar() method.

Note the arguments passed into the ax.bar() method:

  • x_pos is the array with the count of the number of bars.
  • CTEs is our array which contains the means or heights of the bars.
  • yerr=error sets the heights of the error bars and the standard deviations.
  • keyword arguments (align='center', alpha=0.5, ecolor='black', capsize=10) styles the plot.

We'll put a label on the y-axis with the title "Coefficient of thermal expansion (°C-1)" using ax.set_ylabel. We use ax.set_xticks() to feed in our number list to set the bars as numbers 1, 2, 3. Then we add labels to these numbered bars with ax.set_ticklabels(). ax.set_title() and ax.yaxis.grid(True) adds a title and horizontal grid lines.

Finally, we we'll save the figure to a file called bar_plot_with_error_bars.png using matplotlib's plt.savefig() function. The plt.thight_layout() method ensures our axis and labels don't get cut off and are visible.

# Build the plot
fig, ax = plt.subplots()
ax.bar(x_pos, CTEs, yerr=error, align='center', alpha=0.5, ecolor='black', capsize=10)
ax.set_ylabel('Coefficient of Thermal Expansion ($\degree C^{-1}$)')
ax.set_xticks(x_pos)
ax.set_xticklabels(materials)
ax.set_title('Coefficent of Thermal Expansion (CTE) of Three Metals')
ax.yaxis.grid(True)

# Save the figure and show
plt.tight_layout()
plt.savefig('bar_plot_with_error_bars.png')
plt.show()

The final plot looks like this:

plot with error bars