Making pretty, interactive graphs the simple way – Use Plotly.

Using an ESP8266 and some DS18B20 one-wire temperature sensors, I have been automatically recording temperature data from various parts of my pond, to see how it fluctuated with air temperature, depth and filter configuration.

Despite the help I was receiving from the feline fish monitor, I was getting a bit irked at the quality of the graphs I was getting using matplotlib.

Matplotlib has been around since 2003, more than 20 years now. It’s arguably the defacto method of producing graphs in python and it’s not going away. However, it’s also a pain to use and by default produces some quite ugly plots unless you put in the mileage. In fact, when attempting to quickly explore data, Michael L. Waskom’s frustrations with matplotlib were directly related to the production of the seaborn library. “By producing complete graphics from a single function call with minimal
arguments, seaborn facilitates rapid prototyping and exploratory data analysis.”

Seaborn makes use of matplotlib and integrates tightly with pandas provide a neat wrapper for matplotlib functions, allowing you to avoid a lot of the data herding needed to view a graph.

You may think “OK, so seaborn finally tames matplotlib, why should I use anything else?” In short, interactivity. Seaborn and Matplotlib may produce graphs, but a graph alone doesn’t really let you explore the data. If you look at a graph you’re limited to the scale the author thought made sense, you can’t zoom in or out and if one line is behind another, you’re kind of stuck.

Where plotly really shines is with just two lines you can generate your figure and then either save it as the image below, or as an interactive HTML graph such as this.

A full guide to plotly should start here: https://plotly.com/python/getting-started
But in the interim, here’s a quick intro.

Install plotly:

sudo apt-get install -y python3-plotly

I’ve got a honking great data file called pond_temperatures.log that looks like this:

Date, Bottom Sensor, Top Sensor, Air Sensor
2024-04-10 08:36:25,12.00,11.63,11.06
2024-04-10 08:51:29,12.25,11.69,11.69
2024-04-10 09:06:32,12.25,11.63,12.56
...

I want to see how these three variables (Bottom Sensor, Top Sensor and Air Sensor) change over time and explore the data. Below is a quick script that reads that data and generates both a png of it, as well as an explorable HTML version.

import pandas as pd
import plotly.express as px

temps_df = pd.read_csv("pond_temperatures.log")
print(temps_df.tail(3))

fig = px.line(temps_df, x='Date', y=temps_df.columns,title="Pond temperature over time").update_layout(
    xaxis_title="Date", yaxis_title="Temperature (degrees C)")

fig.write_html("temps.html")
fig.write_image("current.png")

Literally, that’s it, seven lines of code:

  • Import libraries (x2)
  • Suck data into a pandas dataframe
  • Show me the last few lines of the data that’s been read (totally optional)
  • Generate a plotly object
  • Save that object as an interactive chart
  • Save it as an image (optional).

If you find the above doesn’t work for you, you may see an error similar to that below:

eoin@mymachine:/tmp$ ./grapher.py

Date Bottom Sensor Top Sensor Air Sensor
2913 2024-06-15 05:54:25 14.75 14.44 11.19
2914 2024-06-15 06:09:29 14.75 14.44 11.31
2915 2024-06-15 06:24:33 14.75 14.44 11.38

Traceback (most recent call last):
File "/tmp/./grapher.py", line 24, in
fig.write_image("current.png")
File "/usr/local/lib/python3.10/dist-packages/plotly/basedatatypes.py", line 3835, in write_image
return pio.write_image(self, *args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/plotly/io/_kaleido.py", line 266, in write_image
img_data = to_image(
File "/usr/local/lib/python3.10/dist-packages/plotly/io/_kaleido.py", line 132, in to_image
raise ValueError(
ValueError:
Image export using the "kaleido" engine requires the kaleido package,
which can be installed using pip:
<strong>$ pip install -U kaleido</strong>

The newer versions of plotly have switched to a package called kaleido to generate the images. On Ubuntu 22.04, this can be installed with:

<strong>eoin@mymachine:/tmp$ pip install -U kaleido</strong>
Defaulting to user installation because normal site-packages is not writeable
Collecting kaleido
Downloading kaleido-0.2.1-py2.py3-none-manylinux1_x86_64.whl.metadata (15 kB)
Downloading kaleido-0.2.1-py2.py3-none-manylinux1_x86_64.whl (79.9 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 79.9/79.9 MB 102.5 MB/s eta 0:00:00
Installing collected packages: kaleido
Successfully installed kaleido-0.2.1

eoin@mymachine:/tmp$ ./grapher.py

Date Bottom Sensor Top Sensor Air Sensor
2913 2024-06-15 05:54:25 14.75 14.44 11.19
2914 2024-06-15 06:09:29 14.75 14.44 11.31
eoin@mymachine:/tmp$ ./grapher.py

Happy plotting!

Author