Rendering Matplotlib AxesSubplots in Streamlit

Hi everyone,

I’m building a streamlit app, and am trying to make use of Seaborn plots in the application. One of my issues is that when I try and render a scatter plot using st.pyplot I get the following error message:

AttributeError: 'AxesSubplot' object has no attribute 'savefig'

Importantly, I do not get these messages with other types of seaborn charts such as sns.catplot. I’m guessing because these charts access different parts of the matplotlib api in different ways. I know seaborn’s catplots are FacetGrid chart objects, while it looks like the scatter plots have the type matplotlib.axes._subplots.AxesSubplot.

I’ve noticed when I try and render the same scatter plot from a pandas dataframe I get the same error message.

Does anyone know how to get around this?

1 Like

Hi @jonathanbechtel, welcome to the Streamlit community!

Can you provide a small code example that fails, so that I can work this out for you?

@randyzwitch sir me too i face the same error here is a code

Can you copy the code in as plain text?

1 Like

fig, ax = plt.subplots() #solved by add this line

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
class Economics():
    def demand_supply_cruve(self , data=None):
        """Graph demand and supply curve
        inputs
        --------------------------------
        Data is a {price:[] , 'Demand':[1,2,3....] , 'Supply':[1,2,3,....] } per unit

        """
        data =  data if data != None else {'price':list(range(0,201,10)) ,'Demand':list(range(0,401,20))[::-1] , 'Supply':list(range(0,401,20))}
        fig, ax = plt.subplots() #solved by add this line 
        ax = sns.lineplot(data=pd.DataFrame(data), x="Demand", y="price")
        return fig

import streamlit as st 
from economics import Economics
st.title("Eco")
eco = Economics()
st.pyplot(eco.demand_supply_cruve())
6 Likes

@AhmedSalam22 :slight_smile: yes your solution for me should work on all Seaborn charts, predefine a Matplotlib ax beforehand and inject the Seaborn chart in it with the ax argument. Thanks for writing this out.

@jonathanbechtel can you confirm the ax trick works for you ?

Best,
Fanilo

2 Likes

I had the same issue - this solution worked like a charm

Best

Steve

1 Like

Cheers guys,

I’m having trouble getting this to work…

import pandas as pd
df = pd.read_csv('titanic.csv')[['Survived', 'Pclass', 'Age', 'Fare']]
df.hist()

This code by itself gives me a multi-plot
multiplot

now i want this to happen in streamlit - and I cannot figure it out…

Closest I could get is

fig, ax = plt.subplots()
ax.hist(df)
st.pyplot(fig)

which gives me this plot, and I cannot figure out how to make the “small multiples” work - any help is appreciated.

I figured it out - you can do this with something like this:

_ = math.ceil(math.sqrt(len(df.columns)))
fig, axs = plt.subplots(_, _, sharey=True)

for i, _c in enumerate(df.columns):
  ax = axs.flat[i]
  ax.hist(df[[_c]], bins=20)
  ax.set_title(_c)

st.pyplot(fig)
1 Like