avatarAlan Jones

Summary

The article explains how to use all of the built-in themes for Plotly with a simple Streamlit component.

Abstract

The article discusses the limitations of Streamlit's support for Plotly themes and provides a solution to use all of the built-in themes for Plotly with a simple Streamlit component. The author explains how to create a new function that uses a Streamlit component and which will plot charts using any of the themes built into Plotly. The article also provides code examples and a test program to demonstrate the use of the new function.

Opinions

  • The author believes that using this technique to draw Plotly charts is more flexible than the native Streamlit function.
  • The author encourages readers to try out the new function and provides resources for further learning about Streamlit.
  • The author recommends an AI service that provides the same performance and functions as ChatGPT Plus(GPT-4) but is more cost-effective.

How to Get All Plotly Themes in Streamlit

You can get around Streamlit’s restrictions and use all of the built-in themes for Plotly with a simple Streamlit component

Built-in Plotly themes — image by author

Plotly themes are normally specified when creating a plot (e.g. template=plotly_dark) but unfortunately, in Streamlit, this theme information gets overwritten when the chart is drawn.

Streamlit only supports the use of two themes and these are specified as an argument to the st.plotly_chart() function. The default is Streamlit’s own theme but you can use the normal Plotly theme, too.

What can you do if you want to be different?

Answer: use a different function!

We are going to see just how easy it is to create a new function that uses a Streamlit component and which will plot your charts using any of the themes built into Plotly.

The image above is a Streamlit app that demonstrates 6 of the built-in Plotly themes that we will use. Here is a closer look at plotly_dark:

The plotly_dark theme — image by author

Streamlit components

Streamlit components come in two flavours: static components, which are blocks of HTML that are inserted into the Streamlit app and bi-directional components that allow values to be returned to the Streamlit app.

A dynamic component might be a user control such as a radio button or menu where the user selects a value to pass back to the program.

A static component could display text in some fancy way. Or, it could be a way of passing data to a chart library — like Plotly — and drawing a chart in HTML.

So, we are going to create a Streamlit component that will take a Plotly figure created in Python, using any theme or other feature provided by Plotly, draw it in HTML and insert it into our Streamlit app. No two-way communication is required, so a static component is fine.

Plotly in HTML/Javascript

It is very simple to draw a chart on an HTML page using Plotly. First, you need to include the Plotly Javascript library:

<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>

And then you call newPlot() from the library something like this:

 Plotly.newPlot("chart", figure);

In the code above the string chart refers to an HTML container for the chart and the argument figure is a definition of the chart in JSON. newPlot() is the Plotly function that creates the chart.

A complete segment of HTML would look like this:

<div id="chart"></div>

<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>

<script type='text/javascript'>
    var figure = JSON.parse(JSON_code_for_the_chart);
    Plotly.newPlot("chart", figure);
</script>

And that is the basis for our Streamlit component.

A Plotly component

A static component is, as mentioned, a block of HTML that will be inserted into the Streamlit app. Our component will look much like the code above but we need to provide it with the JSON definition of the chart to be displayed.

We do this by generating the Plotly chart in the normal way, e.g.

fig = px.scatter(...)

And then converting fig into JSON using the Plotly encoder function, like this:

graphJSON = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)

We can now pass the JSON data into a component so that it will draw a chart in HTML. The component syntax is simple:

components.html(f"""
     HTML code goes here
     """, 
     height=height, width=width)

The HTML code will be written into an iframe that will be inserted into the Streamlit app.

The height and width arguments are optional but we shall use them to ensure that the iframe is the correct size for the image and that the image is not cropped.

Here is all of the code we have discussed combined into a function. We’ll save this as a module so that we can use it in different programs. I’ve called the module plotly_chart.py

import streamlit.components.v1 as components
import json
import plotly

def plotly_chart(fig):
    graphJSON = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
    components.html(f"""
        <div id="chart"></div>
        <script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
        <script type='text/javascript'>
            var figure = JSON.parse('{graphJSON}');
            Plotly.newPlot("chart", figure);
        </script>
        """, 
        height=fig.layout.height, width=fig.layout.width)

Listing 1: plotly_chart.py, a module containing the Streamlit component

The dimensions of the iframe are set to be the same as those of the figure by using its layout attributes.

Testing, testing…

Below we have a test program that imports plotly_chart as pc and invokes the new function to draw a set of charts with different Plotly themes.

The code uses the Gapminder data that is bundled with Plotly and is based on a demonstration from the Plotly documentation. Note that we have set the height and width of the figure. We must do this so that these dimensions can be read by the plot function.

import streamlit as st
import pandas as pd
import plotly.express as px
import plotly_chart as pc

st.title("Plotly themes in Streamlit")
df = px.data.gapminder()

df_2007 = df.query("year==2007")

templates =  ["plotly", "plotly_white", "plotly_dark", 
              "ggplot2", "seaborn", "simple_white", "none"]

for template in templates:
    fig = px.scatter(df_2007,
                     x="gdpPercap", y="lifeExp", 
                     size="pop", color="continent",
                     log_x=True, size_max=60,
                     template=template, 
                     title=f"Gapminder 2007: {template} theme",
                     width=600, height=400,)

    pc.plotly_chart(fig)

Listing 2: a text program — part of this code is adapted from the Plotly template and theme documentation

And that’s about it!

As far as I can see there is no downside to using this technique to draw Plotly charts and it is more flexible than the native Streamlit function. (If you come across a problem, please let me know.)

As ever, thanks for reading. You can find more Streamlit resources on my Streamlit from Scratch website (see below) and subscribe to the Streamlit from Scratch newsletter to get updates and news about Streamlit.

Streamlit
Plotly
Python
Data Visualization
Tutorial
Recommended from ReadMedium