Python data to an interactive chart
A Python list of dictionaries becomes a JavaScript array of objects. This recipe passes per-species statistics from the Palmer Penguins dataset to the browser, where an Observable input chooses the plotted metric. The switch recomputes entirely in the browser. Python is not involved after the initial render.
import marimo as mo
import observablejs as obs
species_stats = [
{"species": "Adelie", "count": 152, "mean_mass_g": 3701},
{"species": "Chinstrap", "count": 68, "mean_mass_g": 3733},
{"species": "Gentoo", "count": 124, "mean_mass_g": 5076},
]
notebook = obs.Notebook(
obs.js(
"""
const metric = view(Inputs.select(
new Map([
["Penguin count", "count"],
["Mean body mass (g)", "mean_mass_g"]
]),
{label: "Metric"}
));
""",
key="metric_control",
),
obs.js(
"""
Plot.barX(speciesStats, {
x: metric,
y: "species",
fill: "species",
tip: {
// This example references a theme variable used by mdx-marimo.
// Replace it with a CSS color or remove `fill` in another host.
fill: "var(--marimo-island-background)"
}
}).plot({
height: 240,
marginLeft: 76,
color: {legend: true},
x: {grid: true, label: metric === "count" ? "Penguins" : "Body mass (g)"},
y: {label: null}
})
""",
key="chart",
),
variables={"speciesStats": species_stats},
)
full_view = notebook.view()
mo.ui.anywidget(full_view)
What this shows
- The
variablesmapping publishes the Python list under the JavaScript namespeciesStats. The chart cell reads it like any graph variable. view(Inputs.select(...))definesmetricin the browser. Changing it invalidates only the chart cell.- A pandas or Polars
DataFrameworks in place of the literal list. It arrives as the same array of row objects. See Variables and serialization.
Variations
- Update the records after render with
notebook.update_variables({"speciesStats": ...}). The chart recomputes while the input keeps its selection. See Python to Observable. - For large tables, register a file with
files=and load it in the browser withFileAttachment(...).csv().