📈 Let's plot with Nextjournal

EDIT. I wasn't aware first, but Lets-plot's main developer already wrote a notebook on the subject. https://nextjournal.com/alshan/lets-plot-quickstart

Lets-plot is a plotting library developed by Jetbrains with the objective of implementing to Python and Kotlin a grammar of graphics similar to the widely popular ggplot2 R library. Python already has great declarative plot packages such as Plotly express, Altair and Plotnine (and others). Lets-plot is designed to be interactive and very close to ggplot2 (although understandably lagging behind in terms of features since it's relatively new).

Working with Lets-plot within Nextjournal didn't work as I expected, but don't worry: easy fixes are coming. While Matplotlib rendered my plots under the Jupyter protocol (the protocol is defined in the Runtime), Lets-plot didn't. Under the Nextjournal protocol, Lets-plot worked but Matplotlib didn't render.

In the aim of working with a single Python runtime, should I adopt Lets-plot and forget about Matplotlib under a Nextjournal protocol, or rather keep Matplotlib and forget Lets-plot under a Jupyter protocol? I contacted Nextjournal's support team, then Andrea Zampino replied that neither is necessary. Let's install lets-plot in two separate runtimes to show how it's done for each protocol.

pip install lets-plot
3.1s
pip install lets-plot
3.2s

🦸 Nextjournal support rescuing

Andrea Zampino offered the fixes in a notebook remixed from the one I sent for a support request. For the example, I'm using 🐧 data.

Jupyter protocol

import pandas as pd
penguins = pd.read_csv("https://gist.githubusercontent.com/ryanorsinger/0e223fb35472c40d449cec4c0737008b/raw/e9688a6b1c2806d9f685f8b9524b80def95f7c97/penguins.csv")
penguins.sample(5)
1.2s

If you like the imperative visualization mode, Matplotlib works directly under the Jupyter protocol.

import matplotlib.pyplot as plt
for i in penguins.species.unique():
  penguins_i = penguins.loc[penguins.species == i, :]
  plt.plot(penguins_i.bill_length_mm, penguins_i.bill_depth_mm, 'o', label = i)
plt.xlabel("Bill length (mm)")
plt.ylabel("Bill depth (mm)")
plt.legend()
0.6s

If you prefer working in declarative mode with Lets-plot, you only need to specify lp.LetsPlot.setup_html(isolated_frame=True).

import lets_plot as lp
lp.LetsPlot.setup_html(isolated_frame=True)
(
  lp.ggplot(penguins, lp.aes(x = 'bill_length_mm', y = 'bill_depth_mm')) + 
  lp.geom_point(lp.aes(color = 'species'))
)
0.4s

Nextjournal protocol

import pandas as pd
penguins = pd.read_csv("https://gist.githubusercontent.com/ryanorsinger/0e223fb35472c40d449cec4c0737008b/raw/e9688a6b1c2806d9f685f8b9524b80def95f7c97/penguins.csv")
0.4s

The Nexjournal protocol will return the Matplotlib object, not the plot. To render the plot, simply add plt.gcf() - gcf for get current figure.

import matplotlib.pyplot as plt
for i in penguins.species.unique():
  penguins_i = penguins.loc[penguins.species == i, :]
  plt.plot(penguins_i.bill_length_mm, penguins_i.bill_depth_mm, 'o', label = i)
plt.xlabel("Bill length (mm)")
plt.ylabel("Bill depth (mm)")
plt.legend()
plt.gcf()
0.7s

As for Lets-plot, it works without LetsPlot.setup_html.

import lets_plot as lp
(
  lp.ggplot(penguins, lp.aes(x = 'bill_length_mm', y = 'bill_depth_mm')) + 
  lp.geom_point(lp.aes(color = 'species'))
)
0.7s
0.3s

Runtimes (2)