7  Static Charts

7.1 Displaying charts made with matplotlib

When we want to display static charts, we will often be using the matplotlib library.

Tip

We can use the st.pyplot() component to display charts created using matplotlib.

Note that certain other non-graph outputs still use matplotlib’s plotting systems - for example, outputs from the wordcloud library and the geopandas plot method are still technically matplotlib plots. For those, we can use st.pyplot() too! This will be covered more in a later chapter.

Below, we create a very simple scatterplot of a dataset.

Note

We have created the fig and ax objects by beginning by creating a single subplot with the plt.subplots function.

This is sometimes referred to as the object-oriented way of writing matplotlib code.

With this method, we then use one of the matplotlib commands, like scatter or bar, and tell it to plot onto the ax object we created.

We can then modify this object using any of the standard matplotlib commands we have become familiar with, such as changing the axis labels.

The final step to ensure the plot is actually displayed is to pass the fig variable to st.pyplot.

import streamlit as st
import pandas as pd
1import matplotlib.pyplot as plt
2from palmerpenguins import load_penguins

3penguins = load_penguins()

4fig, ax = plt.subplots(figsize=(15,10))

5plt.scatter(
6  x=penguins["body_mass_g"],
  y=penguins["bill_length_mm"]
  )

7plt.title("Penguin Body Mass (g) versus Bill Length (mm)")

8ax.set_xlabel("Body Mass (g)")
ax.set_ylabel("Bill Length (mm)")

9st.pyplot(fig)
1
We import the pyplot module of matplotlib using the standard alias ‘plt’
2
We also load in a function from a package that gives us easy access to a dataset of penguin body measurements.
3
We use the load_penguins() function, which returns a pandas dataframe, and assign this to the penguins variable.
4
We then use the plt.subplots function. By just passing in the named argument figsize we get a single blank plot that is relatively 1.5x wider than it is long. The tuple - the two numbers within brackets, separated by a comma - is the width and height of the image. Notice on the left of the = we have fig, ax rather than a single variable name; this is because plt.subplots returns two variables, and this means we can easily access both of these. We always write fig, ax in the same order - this is just a standard matplotlib convention.
5
Now we use our chosen plotting function - in this case, we want a scatterplot.
6
We pass in the values to use for our x column - our horizontal axis - using the format dataframe_variable["column_name"], which passes in our list of values as a pandas series. For these purposes, the pandas series is effectively a fancy list - it will primarily just contain the value for that column for each row in the dataframe. We repeat this for our y (vertical) axis.
7
We pass in a string to use as the title of the graph with the plt.title() function.
8
We can then use various methods of our ax variable to update things such as the x and y axis labels.
9
Finally, we pass the completed figure to the st.pyplot() function, which will make sure it gets displayed in our app.
Note

Note that we don’t have to specify the axis we are plotting on within our plt.scatter() call (i.e. we don’t include ax=ax as one of the arguments) - it’s sufficient to just pass in the data we want to plot, and matplotlib will automatically select the appropriate axis.

7.2 An alternative way of displaying charts made with matplotlib

Instead of using the st.pyplot() function, we may find it easier in some cases to save the output figure and serve that to the user using the st.image() function instead.

import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins

penguins = load_penguins()

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

plt.scatter(
  x=penguins["body_mass_g"],
  y=penguins["bill_length_mm"]
  )

plt.title("Penguin Body Mass (g) versus Bill Length (mm)")

ax.set_xlabel("Body Mass (g)")
ax.set_ylabel("Bill Length (mm)")

1filename = 'penguins_scatter_method_1.png'
2plt.savefig(filename)

3st.image(filename)
1
We set a filename string, including the file extension of .png
2
Next we save the file to local storage - it will save in the same folder relative to our Streamlit app script.
3
Finally, we use st.image() to display the image file we have just created.
Note

We could also write the last 3 lines of code above as

plt.savefig('penguins_scatter_method_1.png')

st.image('penguins_scatter_method_1.png')

though more care must then be taken to ensure that the names are identical! Generally it is better to define the filename variable to reduce repetition.

You can see that functionally this appears nearly identical to what we do above!

7.3 Making use of the available space

Many streamlit components have a parameter called use_container_width.

When set to True in something like st.pyplot, it ensures the output is rescaled to use the maximum available width of the screen.

The parameter is set to False by default, which will result in outputs often not optimally using the available space.

Tip

This can become particularly valuable when we start to explore layout options like columns later in the book.

import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins

penguins = load_penguins()

fig, ax = plt.subplots(figsize=(15,10))
plt.scatter(x=penguins["body_mass_g"], y=penguins["bill_length_mm"])
plt.title("Penguin Body Mass (g) versus Bill Length (mm)")
ax.set_xlabel("Body Mass (g)")
ax.set_ylabel("Bill Length (mm)")

1st.subheader("use_container_width=False")

2st.pyplot(fig)

3st.subheader("use_container_width=True")

4st.pyplot(fig, use_container_width=True)
1
Let’s make ourselves a subheader so we can tell the two outputted plots apart
2
First, we use st.pyplot without the use_container_width argument specified. If not specified, this defaults to False.
3
Now let’s add another subheader.
4
This time, we pass in the same figure to st.pyplot, but this time we specify the use_container_width parameter to be True.

Take a look at the impact this has in the live version of the app below.