Post

Embedding Plotly in a Jekyll Post

Yes, you can include Plotly’s interactive graphics inside your posts, and here is how!

By default, all notebooks are rendered into posts as a two steps process:

  1. The jupyter nbconvert command-line tool is used to convert all notebooks into markdown files
  2. Markdown files in the _posts directory all then all converted into posts, with Jekyll

More details on how to convert notebooks into posts will be avaible in a separate blog post.

The challenge with Plotly graphics is that they are HTML images with Javascript. Thus, directly including the HTML code in the markdown output causes some issues with the Liquid templating system. This is because the generated Javascript contains curly braces, which Liquid tries to interpret.

To solve with this issue, an easy solution is to use the iframe_connected renderer, that will generate the image in a separate HTML file, them include it in the post. This small generated HTML, i.e., the iframe include, does not cause any problem with Liquid templating.

Then, as for other images, it’s a matter of keeping paths to files valid when moving the generated Markdown files to _posts.

For more details on how to configure Plotly’s appearance, see plotting.py.

Sadly, switching between light and dark themes is not possible for the moment…

A more detailed tutorial might follow.

1
2
3
4
import pandas as pd
from plotting import CONFIG
from plotting import express as px
from plotting import graph_objects as go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Example from: https://plotly.com/python/sliders/

df = px.data.gapminder()
fig = px.scatter(
    df,
    x="gdpPercap",
    y="lifeExp",
    animation_frame="year",
    animation_group="country",
    size="pop",
    color="continent",
    hover_name="country",
    log_x=True,
    size_max=55,
    range_x=[100, 100000],
    range_y=[25, 90],
)

fig.show(config=CONFIG)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Example from: https://plotly.com/python/time-series/

df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv"
)

fig = go.Figure(go.Scatter(x=df["Date"], y=df["mavg"]))

fig.update_xaxes(
    rangeslider_visible=True,
    tickformatstops=[
        dict(dtickrange=[None, 1000], value="%H:%M:%S.%L ms"),
        dict(dtickrange=[1000, 60000], value="%H:%M:%S s"),
        dict(dtickrange=[60000, 3600000], value="%H:%M m"),
        dict(dtickrange=[3600000, 86400000], value="%H:%M h"),
        dict(dtickrange=[86400000, 604800000], value="%e. %b d"),
        dict(dtickrange=[604800000, "M1"], value="%e. %b w"),
        dict(dtickrange=["M1", "M12"], value="%b '%y M"),
        dict(dtickrange=["M12", None], value="%Y Y"),
    ],
)

fig.show(config=CONFIG)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Example from: https://plotly.com/python/3d-surface-plots/

# Read data from a csv
z_data = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv"
)

fig = go.Figure(data=[go.Surface(z=z_data.values)])
fig.update_traces(
    contours_z=dict(
        show=True, usecolormap=True, highlightcolor="limegreen", project_z=True
    )
)
fig.update_layout(
    title="Mt Bruno Elevation",
    autosize=False,
    scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64),
    width=500,
    height=500,
    margin=dict(l=65, r=50, b=65, t=90),
)

fig.show(config=CONFIG)
This post is licensed under CC BY 4.0 by the author.