Marimo Notebooks: De Reactieve Alternatief voor Jupyter (Complete Gids 2026)
Marimo is een reactieve Python-notebook die cellen automatisch bijwerkt wanneer variabelen veranderen. In deze gids leer je installatie, workflow, ingebouwde UI-widgets en wanneer Marimo een betere keuze is dan Jupyter voor data science.
Marimo is een open-source reactieve Python-notebook die de bekende problemen van Jupyter oplost door cellen automatisch opnieuw uit te voeren zodra hun onderliggende variabelen veranderen. Verborgen state en volgorde-afhankelijke bugs verdwijnen daarmee volledig. Notebooks worden opgeslagen als leesbare .py-bestanden in plaats van JSON, wat versiebeheer met Git eenvoudig maakt. In deze gids leer je hoe Marimo werkt, hoe je het installeert, wanneer het beter presteert dan Jupyter, en hoe je een reactieve data-analyse workflow bouwt met pandas en Plotly.
Marimo is een reactieve Python-notebook: cellen worden automatisch opnieuw uitgevoerd wanneer hun afhankelijke variabelen wijzigen, waardoor je nooit meer "Run All" hoeft te drukken om reproduceerbare resultaten te krijgen.
Marimo-bestanden worden opgeslagen als zuivere .py-scripts, wat schone diffs in Git oplevert en het uitvoeren als standalone Python-script mogelijk maakt.
Ingebouwde UI-elementen (mo.ui.slider, mo.ui.dropdown, mo.ui.dataframe) maken interactieve dashboards mogelijk zonder aparte Streamlit- of Dash-code.
Notebooks kunnen worden geëxporteerd naar HTML, uitgevoerd in de browser via WebAssembly, of gedeployed als volwaardige web-apps met één commando.
De statische afhankelijkheidsanalyse van Marimo elimineert de belangrijkste bron van niet-reproduceerbare Jupyter-notebooks zoals beschreven in het invloedrijke onderzoek van Pimentel et al. (2019).
Jupyter blijft de standaard voor bestaande workflows en Colab-integraties; Marimo is de sterkere keuze voor nieuwe data-apps, dashboards en team-projecten.
Wat is Marimo en waarom een reactieve notebook?
Marimo is een reactieve Python-notebook, oorspronkelijk ontwikkeld op Stanford door Akshay Agrawal, die in 2024 open-source werd uitgebracht en in 2026 versie 0.9 heeft bereikt met stabiele API's. Het fundamentele idee is simpel: de notebook parseert je code statisch, bouwt een gerichte acyclische grafiek (DAG) van variabele-afhankelijkheden, en werkt bij elke wijziging alleen de getroffen cellen bij. Dit is analoog aan hoe een spreadsheet werkt. Je verandert een cel, en alle formules die ervan afhangen worden onmiddellijk herberekend.
Waarom is dit belangrijk? In een klassieke Jupyter-notebook is de zichtbare celvolgorde niet gelijk aan de uitvoeringsvolgorde. Een cel die je bovenaan bewerkt maar niet opnieuw uitvoert kan een variabele bevatten met verouderde waarden, terwijl cellen eronder werken met de oude versie in geheugen. Ik ben zelf een aantal keer flink onderuit gegaan door dat gedrag, meestal net voordat een collega een demo ging bekijken. Het bekende Rules of Machine Learning-artikel van Google en het onderzoek "A Large-Scale Study About Quality and Reproducibility of Jupyter Notebooks" (Pimentel et al., 2019) toonden aan dat meer dan 36% van publieke Jupyter-notebooks niet reproduceerbaar was. De belangrijkste oorzaak was juist deze verborgen state.
Marimo lost dit op door drie architecturale keuzes: geen verborgen state (variabelen zijn altijd consistent met de cellen), pure Python-opslag (geen JSON met ingebedde outputs), en een strikte regel dat elke variabele slechts in één cel gedefinieerd mag worden. Dat laatste voelt in eerste instantie streng, maar dwingt schone, herbruikbare code af. Vergelijkbaar met hoe type hints in Python 3.13 aanvankelijk als beperkend werden ervaren.
Marimo vs Jupyter: de belangrijkste verschillen
Voordat we in de code duiken, is het nuttig om beide tools naast elkaar te plaatsen. De volgende vergelijking is gebaseerd op Marimo 0.9 (juli 2026) en JupyterLab 4.3, de meest recente stabiele releases op moment van schrijven.
Eigenschap
Marimo 0.9
JupyterLab 4.3
Uitvoeringsmodel
Reactief (DAG)
Imperatief (cel-per-cel)
Bestandsformaat
Pure .py
JSON .ipynb
Git-diff kwaliteit
Uitstekend, leesbaar
Matig, vereist nbdime
Verborgen state
Onmogelijk per ontwerp
Veel voorkomend
Ingebouwde UI-widgets
Ja (native, reactief)
Alleen via ipywidgets
Deployment als app
Eén commando (marimo run)
Extra tool nodig (Voilà)
Uitvoeren als script
Direct: python notebook.py
Vereist nbconvert
Ecosysteem
Groeiend (0.9, jong)
Volwassen (10+ jaar)
Colab / Kaggle-support
Beperkt
Native ondersteund
De belangrijkste conclusie? Marimo wint op reproduceerbaarheid, versiebeheer en app-deployment, terwijl Jupyter wint op ecosysteem, cloudintegratie en breedte van ondersteunde extensies. Voor lange-termijn dataprojecten waar meerdere mensen aan werken (inclusief de datacleaning workflows met Pandas 3.0 die we eerder besproken hebben) is de Git-vriendelijkheid van Marimo een enorme win.
Marimo installeren en je eerste notebook maken
Marimo werkt op Python 3.9 en hoger. De aanbevolen installatiemethode in 2026 is via uv, de snelle Python-package manager van Astral, maar pip werkt ook prima. Ik demonstreer beide.
# Optie 1: met uv (aanbevolen in 2026)
uv pip install marimo
# Optie 2: met pip
pip install marimo
# Verifieer installatie
marimo --version
# Verwachte output: marimo 0.9.x
# Start een nieuwe notebook
marimo edit mijn_notebook.py
Het commando marimo edit opent je standaardbrowser en toont een lege notebook. Merk op dat je een bestand vóór gebruik een naam geeft. Marimo werkt met concrete .py-bestanden, niet met untitled buffers zoals Jupyter. Dat past bij een script-first mentaliteit.
Laten we een minimaal voorbeeld schrijven dat de reactieve aard demonstreert. Maak drie cellen aan:
# Cel 1: importeer pandas
import pandas as pd
import marimo as mo
# Cel 2: creëer een DataFrame
df = pd.DataFrame({
"product": ["A", "B", "C", "D"],
"verkoop": [120, 340, 210, 580],
"kosten": [80, 200, 150, 400],
})
# Cel 3: bereken winst
df["winst"] = df["verkoop"] - df["kosten"]
df
Wanneer je nu in cel 2 de waarde 580 verandert naar 750, wordt cel 3 automatisch opnieuw uitgevoerd en zie je de bijgewerkte winst-kolom onmiddellijk. In Jupyter zou je expliciet Shift+Enter moeten drukken op cel 3, of zelfs "Run All Below", met alle risico's van vergeten cellen. Eerlijk, dit alleen al bespaart je een hoop hoofdpijn tijdens een lange middag data-analyse.
Reactieve uitvoering in de praktijk met pandas
De echte kracht van Marimo wordt zichtbaar in complexere data science workflows. Laten we een realistisch voorbeeld bekijken: een verkoopanalyse waarin we filteren, aggregeren en visualiseren. In een Jupyter-notebook zou je bij elke wijziging van een filterparameter handmatig meerdere cellen opnieuw moeten uitvoeren. In Marimo gebeurt dit automatisch.
import marimo as mo
import pandas as pd
import plotly.express as px
# Laad een voorbeeld-dataset
url = "https://raw.githubusercontent.com/plotly/datasets/master/tips.csv"
tips = pd.read_csv(url)
# Definieer een filter (dit wordt in de volgende sectie een UI-slider)
min_totaal = 15.0
# Filter en aggregeer
gefilterd = tips[tips["total_bill"] >= min_totaal]
per_dag = (
gefilterd
.groupby("day", observed=True)
.agg(gem_fooi=("tip", "mean"), aantal=("tip", "size"))
.reset_index()
)
# Visualiseer
fig = px.bar(
per_dag,
x="day",
y="gem_fooi",
title=f"Gemiddelde fooi per dag (rekening ≥ €{min_totaal})",
text_auto=".2f",
)
fig
Zodra je min_totaal aanpast naar bijvoorbeeld 25.0, worden de gefilterd-cel, de per_dag-aggregatie én de Plotly-visualisatie automatisch opnieuw berekend. Dit voelt bijna magisch, maar het is puur mechanica. Marimo heeft bij het parsen van de code de afhankelijkheidsgrafiek min_totaal → gefilterd → per_dag → fig opgebouwd en volgt die trouw.
Voor zwaardere workloads (denk aan analyses met miljoenen rijen zoals in onze DuckDB Python gids) biedt Marimo lazy execution en caching via mo.cache. Hiermee worden dure berekeningen alleen opnieuw uitgevoerd wanneer de inputs daadwerkelijk zijn veranderd. Vergelijkbaar met @functools.lru_cache, maar dan op notebookniveau.
import marimo as mo
import duckdb
@mo.cache
def query_verkoop(min_bedrag: float) -> pd.DataFrame:
con = duckdb.connect("verkoop.db")
return con.execute(
"SELECT product, SUM(bedrag) AS totaal FROM transacties "
"WHERE bedrag >= ? GROUP BY product",
[min_bedrag],
).fetchdf()
# Alleen opnieuw uitgevoerd als min_bedrag verandert
resultaat = query_verkoop(100.0)
Interactieve UI-elementen voor data-analyse
De ingebouwde UI-widgets van Marimo (sliders, dropdowns, tekstvelden, datepickers en zelfs volledig interactieve dataframes) tillen een notebook op naar een lichtgewicht data-app. Belangrijk: elk widget is reactief aangesloten op de afhankelijkheidsgrafiek. Verander de slider, en alle afhankelijke cellen updaten mee.
import marimo as mo
import pandas as pd
import plotly.express as px
# Cel 1: maak een slider
min_totaal = mo.ui.slider(
start=5,
stop=50,
step=5,
value=15,
label="Minimum rekening (€)",
)
min_totaal
# Cel 2: filter (leest .value van de slider)
tips = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/tips.csv"
)
gefilterd = tips[tips["total_bill"] >= min_totaal.value]
# Cel 3: visualiseer
per_dag = (
gefilterd
.groupby("day", observed=True)["tip"]
.mean()
.reset_index(name="gem_fooi")
)
px.bar(per_dag, x="day", y="gem_fooi", text_auto=".2f")
Wanneer je de slider versleept, worden cel 2 en cel 3 onmiddellijk opnieuw uitgevoerd, zonder dat je één regel event-handling code hoeft te schrijven. Voor complexere lay-outs biedt Marimo mo.hstack, mo.vstack en mo.md() voor Markdown-mixing. Een dropdown, tekstveld en checkbox zien er zo uit:
Voor data-exploratie is mo.ui.dataframe(df) bijzonder waardevol. Het rendert je DataFrame als een interactieve tabel met filtering, sortering en kolomtransformaties, en de resulterende (getransformeerde) DataFrame is beschikbaar als .value voor gebruik in andere cellen. Dat is functionaliteit die in Jupyter minstens een pandas-profiling- of ITables-installatie zou vereisen.
Marimo notebooks delen: web-apps, WASM en scripts
Nadat je een analyse hebt gebouwd, wil je die delen. Marimo ondersteunt vier distributiemodi, elk met een eigen use case. Deze flexibiliteit is een van de sterkste argumenten om over te stappen. Je hoeft namelijk geen aparte Streamlit-, Dash- of FastAPI-app te bouwen voor deployment.
1. Interactieve web-app met marimo run. Dit commando serveert de notebook in "app-modus": codecellen worden verborgen en alleen de outputs en UI-elementen zijn zichtbaar. Perfect voor dashboards.
# Serveer als app op poort 2718
marimo run mijn_notebook.py --port 2718
# Achter een reverse proxy
marimo run mijn_notebook.py --host 0.0.0.0 --headless
2. Statische HTML-export. Voor rapportages die je per e-mail wilt versturen of op een intranet plaatsen.
marimo export html mijn_notebook.py -o rapport.html
3. WebAssembly (WASM) in de browser. Marimo kan volledig client-side draaien via Pyodide, zonder server. Ideaal voor educatief materiaal of interactieve blogposts.
4. Uitvoeren als standaard Python-script. Omdat het bestand pure Python is, kun je het gewoon draaien vanaf de commandoregel of importeren als module in ETL-pipelines.
python mijn_notebook.py
Dat vierde punt is subtiel maar krachtig: je kunt dezelfde codebase gebruiken voor interactieve exploratie én productie-scripts. In Jupyter-workflows moet je vaak code kopiëren uit notebooks naar .py-bestanden voor deployment, wat een klassieke bron van drift is tussen ontwikkeling en productie.
Wanneer kies je voor Marimo (en wanneer niet)?
Ondanks alle voordelen is Marimo geen universele vervanger voor Jupyter. Op basis van mijn ervaring met beide tools in team-omgevingen zijn dit de beslissingscriteria die ik hanteer.
Kies Marimo als:
Je werkt in een team dat notebooks via Git versioneert.
Je bouwt interne dashboards of data-apps en wilt geen aparte Streamlit-codebase onderhouden.
Reproduceerbaarheid is kritisch, bijvoorbeeld voor onderzoek, audits of ML-experimenten.
Je waardeert een script-first workflow (pure .py-bestanden, uitvoerbaar met python).
Je begint met een nieuwe analyse. De leercurve is korter dan het lijkt.
Blijf bij Jupyter als:
Je werkt intensief met Google Colab, Kaggle-notebooks of andere cloudplatforms die Marimo (nog) niet ondersteunen.
Je bestaande codebase leunt zwaar op Jupyter-specifieke extensies (zoals %%sql magics of nbdev).
Je collega's zijn niet bereid om over te stappen. Team-consistentie weegt zwaar.
Je hebt notebooks die opzettelijk niet-lineair worden gebruikt (experimenteel schrappen en re-runnen buiten volgorde). Dat past minder goed bij Marimo's reactieve model.
Een pragmatisch pad: gebruik Jupyter voor initiële exploratie en losse experimenten, en Marimo voor "geconsolideerde" notebooks die anderen zullen bekijken, hergebruiken of deployen. Deze hybride benadering combineert de flexibiliteit van Jupyter met de reproduceerbaarheid van Marimo. Ik pas dit zelf al maanden zo toe, en het scheelt eindeloos gepiel met kernels die halverwege een middag opeens niet meer synchroon lopen.
Voor lezers die bezig zijn met bredere Python-data-tooling, bekijk ook onze Polars vs Pandas vergelijking. Polars werkt uitstekend samen met Marimo dankzij zijn expliciete, immutable API die past bij het reactieve model.
Veelgestelde vragen
Wat is Marimo en waar wordt het voor gebruikt?
Marimo is een open-source reactieve Python-notebook voor data science, data-apps en interactieve documenten. Het onderscheidt zich van Jupyter doordat cellen automatisch opnieuw worden uitgevoerd wanneer hun afhankelijke variabelen wijzigen, en notebooks worden opgeslagen als leesbare .py-bestanden in plaats van JSON.
Is Marimo beter dan Jupyter voor data science?
Marimo is beter voor reproduceerbaarheid, Git-versiebeheer en het bouwen van deployable data-apps. Jupyter is beter voor exploratieve losse experimenten, cloudintegraties (Colab, Kaggle) en werken met een ouder ecosysteem van extensies. Voor nieuwe teamprojecten in 2026 is Marimo vaak de sterkere keuze.
Kan Marimo bestaande Jupyter-notebooks importeren?
Ja. Het commando marimo convert mijn_notebook.ipynb zet een Jupyter-notebook om naar Marimo's .py-formaat. Let op: cellen met verborgen state of dubbel gedefinieerde variabelen worden bij conversie zichtbaar en moeten mogelijk worden opgelost.
Is Marimo gratis en open-source?
Ja. Marimo staat onder de Apache 2.0-licentie op GitHub en is volledig gratis, zowel voor persoonlijk als commercieel gebruik. Er is geen betaalde "pro"-versie die functionaliteit achter een paywall zet.
Werkt Marimo goed met pandas en NumPy?
Uitstekend. Marimo werkt prima met pandas 3.0, NumPy 2.x, Polars, DuckDB, scikit-learn en alle mainstream Python data-libraries. De reactieve engine is agnostisch voor welke datalibrary je gebruikt; hij analyseert alleen Python-variabelen-afhankelijkheden.
Hoe deploy ik een Marimo-notebook als web-app?
Met één commando: marimo run mijn_notebook.py --host 0.0.0.0 --port 8080. Dit serveert je notebook als een web-app met alleen de outputs en UI-widgets zichtbaar. Voor productiegebruik draai je dit achter een reverse proxy zoals Nginx of Caddy, of in een Docker-container.
LitServe, BentoML of kaal FastAPI voor Python ML-modellen in productie? Vergelijking van p99-latency, dynamic batching, cost per prediction en migratie-strategie, met echte benchmarks op een A10G.
Leer hoe DuckDB met Python razendsnelle SQL-analyses uitvoert op Pandas, Polars en Parquet-bestanden, inclusief praktische voorbeelden en benchmarks tegen Pandas.
Leer data opschonen met Pandas 3.0 — van ontbrekende waarden en duplicaten tot uitschieters en herbruikbare cleaning pipelines. Inclusief werkende Python-codevoorbeelden die je direct kunt gebruiken.