Leverage Plotly Express + Bootstrap to Create Great Looking HTML Reports

You’ve just finished a stellar analysis in a Jupyter notebook and you are ready to share your work with colleagues. However, they’ve never heard of a Jupyter notebook. In this post, I’ll walk you through creating an HTML export that leverages Bootstrap to create a styled exportable report from a Jupyter notebook.

Summary

For those familiar with Bootstrap and Plotly Express, here is the 30-second overview. Create two variables with the start and end of your HTML document. Then sandwich your Plotly charts into the body of your HTML file. Here is a simplified example:

with open('file_name.html', 'a') as f:
    f.write(html_start)
	f.write(fig.to_html(full_html=False, include_plotlyjs='cdn'))
    f.write(html_end)

Further Explanation

Why use an HTML file?

Platform independence. Your audience just opens the file using their browser. They don’t need a special application or worry about what operating system they use.

Works on mobile. Bootstrap is responsive on mobile by design. This makes it an effortless experience for anyone to open your report on any device.

Maintain interactivity. Plotly charts are wonderful because the user can interact with the charts. You will lose this if you try to put the chart into a PowerPoint or email it.

It’s easy to create an HTML file in Python. Creating the HTML file from a Jupyter notebook is relatively straightforward. You only need a few lines of code to create the HTML file.

Add Automation. You can create a function that makes the chart, loop through it, and quickly add a bunch of charts to your HTML document.

Nobody wants to see your code. Unless your audience includes other Data Scientists, having your final deliverable be the Jupyter notebook itself can be confusing and distracting for your audience.

Process Overview

  1. Create your Plotly charts in your Jupyter notebook and save them each to a unique variable
  2. Create a variable with the HTML header information which includes the bootstrap styles
  3. Create another variable with the HTML elements that finish the body section, add the javascript files from bootstrap, and close the HTML document
  4. Create the HTML document and add the Plotly charts to the body section

Step 1: Create your Plotly Charts

I’m assuming you are already familiar with Plotly so here is just an example of creating a chart and assigning it to a variable. This is a chart from my COVID-19 Analysis and you can click on the link to see the entire notebook.

The thing to point out here is that this chart is assigned to the variable fig1. It’s important to keep every Plotly chart as their own variable so that we can call them later on when creating the HTML document.

fig1 = go.Figure()
fig1.add_trace(go.Bar(x=us_daily_df_new_per_day.index, 
                      y=us_daily_df_new_per_day['positiveIncrease'], 
                      marker_color='lightblue', 
                      name= 'Positive Cases',
                      hovertemplate = '%{y:,.0f}'
                     ))
fig1.add_trace(go.Scatter(x=us_daily_df_new_per_day_rolling.index, 
                          y=us_daily_df_new_per_day_rolling['positiveIncrease'], 
                          marker_color='#000080', 
                          name = '7 Day Moving Avg.',
                         hovertemplate ='%{y:,.0f}'))


fig1.update_layout(template='none', height=500, autosize=True,hovermode="x", title='New Daily COVID Cases',legend=dict(
    orientation="h",
    yanchor="bottom",
    y=1.02,
    xanchor="right",
    x=1
))

fig1.show()

Step 2: Create a Variable with the Opening HTML Elements

Next, I create a string variable that has the head elements and opening body elements of my HTML documents. Here is where you can add any additional styles and body elements before your first chart appears.

Notice that right after the opening of my body element that I have an h1 and h4 element in this variable. Alternatively, I could wait to add these until step 4.

html_start = '''
<!doctype html>
<html lang="en">
  <head>

    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">

    <!-- Font Awesome -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <style type="text/css">
      
      h1,h2,h3 {
        padding-top: 50px;
      }

      .center {
        text-align: center;
      }

    </style>

    <title>COVID Dashboard</title>

  </head>

  <div class = "container">

  <body>

      <h1>COVID-19 Report</h1>
      <h4 style="color:grey"> '''+dt.datetime.strftime(dt.datetime.now(),'%b %-d, %Y')+'''</h4>
     
'''

Step 3: Create another variable with the Ending HTML Elements

Next, I’ll create a second string variable that closes any open div, the body, and HTML tags. I also have the javascript files for the bootstrap elements.

html_end ='''

</div>
</div>

<!-- Optional JavaScript; choose one of the two! -->

    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>

    <!-- Option 2: jQuery, Popper.js, and Bootstrap JS
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" crossorigin="anonymous"></script>
    -->

  </body>
</html>

'''

Step 4: Export Plotly Charts as HTML

Finally, we can create the actual HTML document. You’ll see that we start by writing the opening HTML elements to the file which is followed by writing the Plotly charts. Adding other HTML elements is easy by also passing in the string to the f.write() function.

with open('covid_report.html', 'a') as f:
    f.write(html_start)
    f.write('<h2>US National Data</h2>')
    f.write(fig.to_html(full_html=False, include_plotlyjs='cdn'))

    f.write('<h2>World Data</h2>')
    f.write(fig2.to_html(full_html=False, include_plotlyjs='cdn'))

    f.write(html_end)

Once the code has executed, you’ll see an HTML file in your directory.

If you run the block of code more than once, you’ll likely receive an error because the file already exists. I typically just delete the file and then re-run the code. Here is how you can remove the file:

os.remove('covid_report.html')

Lastly, here is where you can also create the charts by looping through a function. To do that, you will need to create a function that returns the figure. Then you can loop through it like this:

for i in lst:
  f.write(chart_func(i).to_html(full_html=False, include_plotlyjs='cdn'))  

How do I share the HTML file?

Since it’s a static file, you can throw it into an S3 bucket and make it public. You’ll then have a link that others can open just like they would any other site. You could also use a service like Netlify to host the document for free as well.

I use Bluehost for my site and I can easily just add an HTML file to my directory. Here is what the final report looks like.

I’ve tried using Google Drive but it appears that you can no longer host a static website through Drive. You could create a Google Site but you have to embed your code rather than just uploading it. If there is an easy way to do this in Google Drive, comment below!

You could also send the HTML file to a colleague. However, non-technical colleagues might not understand that they have to download it and view it in their browser. It’s also possible that it opens in a text editor by default.

Final Thoughts

In this post, I’ve walked through incorporating your Plotly Express charts into an HTML file to make sharing your analysis easy and so that it looks professional. I have chosen Bootstrap because they have made it so easy to create a responsive HTML site.

To take this one step further, consider learning how to create web apps using the Plotly Dash framework. There is a Bootstrap component library for Dash.

Thanks for reading!


Posted

in

by

Tags: