Plotting¶
marimo supports most major plotting libraries, including Matplotlib, Seaborn, Plotly, and Altair. Just import your plotting library of choice and use it as you normally would.
For more information about plotting, see the plotting guide.
Reactive charts with Altair¶
/// marimo-embed size: xlarge
@app.cell
async def __():
import pandas as pd
import pyodide
import micropip
import json
await micropip.install('altair')
import altair as alt
return
@app.cell
def __():
cars = pd.DataFrame(json.loads(
pyodide.http.open_url('https://vega.github.io/vega-datasets/data/cars.json').read()
))
chart = mo.ui.altair_chart(alt.Chart(cars).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon',
color='Origin'
))
return
@app.cell
def __():
mo.vstack([chart, mo.ui.table(chart.value)])
return
///
Disabling automatic selection¶
marimo automatically adds a default selection based on the mark type, however, you may want to customize the selection behavior of your Altair chart. You can do this by setting chart_selection
and legend_selection
to False
, and using .add_params
directly on your Altair chart.
# Create an interval selection
brush = alt.selection_interval(encodings=["x"])
_chart = (
alt.Chart(traces, height=150)
.mark_line()
.encode(x="index:Q", y="value:Q", color="traces:N")
.add_params(brush) # add the selection to the chart
)
chart = mo.ui.altair_chart(
_chart,
# disable automatic selection
chart_selection=False,
legend_selection=False
)
chart # You can now access chart.value to get the selected data
marimo.ui.altair_chart
¶
altair_chart(
chart: Chart,
chart_selection: Literal["point"]
| Literal["interval"]
| bool = True,
legend_selection: list[str] | bool = True,
*,
label: str = "",
on_change: Optional[
Callable[[ChartDataType], None]
] = None
)
Bases: UIElement[ChartSelection, ChartDataType]
Make reactive charts with Altair.
Use mo.ui.altair_chart
to make Altair charts reactive: select chart data
with your cursor on the frontend, get them as a dataframe in Python!
Supports polars, pandas, and arrow DataFrames.
Examples:
import altair as alt
import marimo as mo
from vega_datasets import data
chart = (
alt.Chart(data.cars())
.mark_point()
.encode(
x="Horsepower",
y="Miles_per_Gallon",
color="Origin",
)
)
chart = mo.ui.altair_chart(chart)
ATTRIBUTE | DESCRIPTION |
---|---|
value |
A dataframe of the plot data filtered by the selections.
TYPE:
|
dataframe |
A dataframe of the unfiltered chart data.
TYPE:
|
selections |
The selection of the chart; this may be an interval along the name of an axis or a selection of points.
TYPE:
|
PARAMETER | DESCRIPTION |
---|---|
chart
|
An Altair Chart object.
TYPE:
|
chart_selection
|
Selection type, "point", "interval", or a bool. Defaults to True which will automatically detect the best selection type. This is ignored if the chart already has a point/interval selection param.
TYPE:
|
legend_selection
|
List of legend fields (columns) for which to enable selection, True to enable selection for all fields, or False to disable selection entirely. This is ignored if the chart already has a legend selection param. Defaults to True.
TYPE:
|
label
|
Markdown label for the element. Defaults to "".
TYPE:
|
on_change
|
Optional callback to run when this element's value changes. Defaults to None.
TYPE:
|
dataframe
instance-attribute
¶
apply_selection
¶
Apply the selection to a DataFrame.
This method is useful when you have a layered chart and you want to apply the selection to a DataFrame.
PARAMETER | DESCRIPTION |
---|---|
df
|
A DataFrame to apply the selection to.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
ChartDataType
|
A DataFrame of the plot data filtered by the selections.
TYPE:
|
Examples:
batch
¶
batch(**elements: UIElement[JSONType, object]) -> batch
Convert an HTML object with templated text into a UI element.
This method lets you create custom UI elements that are represented by arbitrary HTML.
Example.
user_info = mo.md(
'''
- What's your name?: {name}
- When were you born?: {birthday}
'''
).batch(name=mo.ui.text(), birthday=mo.ui.date())
In this example, user_info
is a UI Element whose output is markdown
and whose value is a dict with keys 'name'
and 'birthday
'
(and values equal to the values of their corresponding elements).
Args.
- elements: the UI elements to interpolate into the HTML template.
callout
¶
callout(
kind: Literal[
"neutral", "danger", "warn", "success", "info"
] = "neutral"
) -> Html
Create a callout containing this HTML element.
A callout wraps your HTML element in a raised box, emphasizing its
importance. You can style the callout for different situations with the
kind
argument.
Examples.
form
¶
form(
label: str = "",
*,
bordered: bool = True,
loading: bool = False,
submit_button_label: str = "Submit",
submit_button_tooltip: Optional[str] = None,
submit_button_disabled: bool = False,
clear_on_submit: bool = False,
show_clear_button: bool = False,
clear_button_label: str = "Clear",
clear_button_tooltip: Optional[str] = None,
validate: Optional[
Callable[[Optional[JSONType]], Optional[str]]
] = None,
on_change: Optional[
Callable[[Optional[T]], None]
] = None
) -> form[S, T]
Create a submittable form out of this UIElement
.
Use this method to create a form that gates the submission
of a UIElement
s value until a submit button is clicked.
The value of the form
is the value of the underlying
element the last time the form was submitted.
Examples.
Convert any UIElement
into a form:
Combine with HTML.batch
to create a form made out of multiple
UIElements
:
form = (
mo.ui.md(
'''
**Enter your prompt.**
{prompt}
**Choose a random seed.**
{seed}
'''
)
.batch(
prompt=mo.ui.text_area(),
seed=mo.ui.number(),
)
.form()
)
Args.
label
: A text label for the form.bordered
: whether the form should have a borderloading
: whether the form should be in a loading statesubmit_button_label
: the label of the submit buttonsubmit_button_tooltip
: the tooltip of the submit buttonsubmit_button_disabled
: whether the submit button should be disabledclear_on_submit
: whether the form should clear its contents after submittingshow_clear_button
: whether the form should show a clear buttonclear_button_label
: the label of the clear buttonclear_button_tooltip
: the tooltip of the clear buttonvalidate
: a function that takes the form's value and returns an error message if the value is invalid, orNone
if the value is valid
send_message
¶
Send a message to the element rendered on the frontend from the backend.
Performance and Data Transformers¶
Altair has a concept of data transformers, which can be used to improve performance.
Such examples are:
- pandas Dataframe has to be sanitized and serialized to JSON.
- The rows of a Dataframe might need to be sampled or limited to a maximum number.
- The Dataframe might be written to a
.csv
or.json
file for performance reasons.
By default, Altair uses the default
data transformer, which is the slowest in marimo. It is limited to 5000 rows (although we increase this to 20_000
rows as marimo can handle this). This includes the data inside the HTML that is being sent over the network, which can also be limited by marimo's maximum message size.
It is recommended to use the marimo_csv
data transformer, which is the most performant and can handle the largest datasets: it converts the data to a CSV file which is smaller and can be sent over the network. This can handle up to +400,000 rows with no issues.
When using mo.ui.altair_chart
, we automatically set the data transformer to marimo_csv
for you. If you are using Altair directly, you can set the data transformer using the following code:
Reactive plots with Plotly¶
mo.ui.plotly only supports scatter plots, treemaps charts, and sunbursts charts.
marimo can render any Plotly plot, but mo.ui.plotly
only
supports reactive selections for scatter plots, treemaps charts, and sunbursts charts. If you require other kinds of
selection, consider using mo.ui.altair_chart
.
marimo.ui.plotly
¶
plotly(
figure: Figure,
config: Optional[Dict[str, Any]] = None,
renderer_name: Optional[str] = None,
*,
label: str = "",
on_change: Optional[Callable[[JSONType], None]] = None
)
Bases: UIElement[PlotlySelection, List[Dict[str, Any]]]
Make reactive plots with Plotly.
Use mo.ui.plotly
to make plotly plots reactive: select data with your
cursor on the frontend, get them as a list of dicts in Python!
This function currently only supports scatter plots, treemaps charts, and sunbursts charts.
Examples:
import plotly.express as px
import marimo as mo
from vega_datasets import data
_plot = px.scatter(
data.cars(), x="Horsepower", y="Miles_per_Gallon", color="Origin"
)
plot = mo.ui.plotly(_plot)
Or with custom configuration:
ATTRIBUTE | DESCRIPTION |
---|---|
value |
A dict of the plot data.
TYPE:
|
ranges |
The selection of the plot; this may be an interval along the name of an axis.
TYPE:
|
points |
The selected points data.
TYPE:
|
indices |
The indices of selected points.
TYPE:
|
PARAMETER | DESCRIPTION |
---|---|
figure
|
A plotly Figure object.
TYPE:
|
config
|
Configuration for the plot. This is a dictionary that is passed directly to plotly. See the plotly documentation for more information: https://plotly.com/javascript/configuration-options/ This takes precedence over the default configuration of the renderer. Defaults to None.
TYPE:
|
renderer_name
|
Renderer to use for the plot.
If this is not provided, the default renderer (
TYPE:
|
label
|
Markdown label for the element. Defaults to "".
TYPE:
|
on_change
|
Callback to run when this element's value changes. Defaults to None.
TYPE:
|
indices
property
¶
Get the indices of selected points in the plot.
RETURNS | DESCRIPTION |
---|---|
List[int]
|
List[int]: A list of indices corresponding to the selected points. Returns an empty list if no points are selected. |
points
property
¶
Get the selected points data from the plot.
RETURNS | DESCRIPTION |
---|---|
List[Dict[str, Any]]
|
List[Dict[str, Any]]: A list of dictionaries containing the data for each selected point. Returns an empty list if no points are selected. |
ranges
property
¶
Get the range selection of the plot.
RETURNS | DESCRIPTION |
---|---|
Dict[str, List[float]]
|
Dict[str, List[float]]: A dictionary mapping field names to their selected ranges, where each range is a list of [min, max] values. Returns an empty dict if no range selection exists. |
batch
¶
batch(**elements: UIElement[JSONType, object]) -> batch
Convert an HTML object with templated text into a UI element.
This method lets you create custom UI elements that are represented by arbitrary HTML.
Example.
user_info = mo.md(
'''
- What's your name?: {name}
- When were you born?: {birthday}
'''
).batch(name=mo.ui.text(), birthday=mo.ui.date())
In this example, user_info
is a UI Element whose output is markdown
and whose value is a dict with keys 'name'
and 'birthday
'
(and values equal to the values of their corresponding elements).
Args.
- elements: the UI elements to interpolate into the HTML template.
callout
¶
callout(
kind: Literal[
"neutral", "danger", "warn", "success", "info"
] = "neutral"
) -> Html
Create a callout containing this HTML element.
A callout wraps your HTML element in a raised box, emphasizing its
importance. You can style the callout for different situations with the
kind
argument.
Examples.
form
¶
form(
label: str = "",
*,
bordered: bool = True,
loading: bool = False,
submit_button_label: str = "Submit",
submit_button_tooltip: Optional[str] = None,
submit_button_disabled: bool = False,
clear_on_submit: bool = False,
show_clear_button: bool = False,
clear_button_label: str = "Clear",
clear_button_tooltip: Optional[str] = None,
validate: Optional[
Callable[[Optional[JSONType]], Optional[str]]
] = None,
on_change: Optional[
Callable[[Optional[T]], None]
] = None
) -> form[S, T]
Create a submittable form out of this UIElement
.
Use this method to create a form that gates the submission
of a UIElement
s value until a submit button is clicked.
The value of the form
is the value of the underlying
element the last time the form was submitted.
Examples.
Convert any UIElement
into a form:
Combine with HTML.batch
to create a form made out of multiple
UIElements
:
form = (
mo.ui.md(
'''
**Enter your prompt.**
{prompt}
**Choose a random seed.**
{seed}
'''
)
.batch(
prompt=mo.ui.text_area(),
seed=mo.ui.number(),
)
.form()
)
Args.
label
: A text label for the form.bordered
: whether the form should have a borderloading
: whether the form should be in a loading statesubmit_button_label
: the label of the submit buttonsubmit_button_tooltip
: the tooltip of the submit buttonsubmit_button_disabled
: whether the submit button should be disabledclear_on_submit
: whether the form should clear its contents after submittingshow_clear_button
: whether the form should show a clear buttonclear_button_label
: the label of the clear buttonclear_button_tooltip
: the tooltip of the clear buttonvalidate
: a function that takes the form's value and returns an error message if the value is invalid, orNone
if the value is valid
send_message
¶
Send a message to the element rendered on the frontend from the backend.
Interactive matplotlib¶
marimo.mpl.interactive
¶
interactive(figure: Union[Figure, SubFigure, Axes]) -> Html
Render a matplotlib figure using an interactive viewer.
The interactive viewer allows you to pan, zoom, and see plot coordinates on mouse hover.
Example:
Args:
- figure: a matplotlib
Figure
orAxes
object
Returns:
- An interactive matplotlib figure as an
Html
object
Source code in marimo/_plugins/stateless/mpl/_mpl.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
|
Leafmap support¶
marimo supports rendering Leafmap maps using the folium
and plotly
backends.
Other plotting libraries¶
You can use all the popular plotting libraries with marimo. Such as: