render_jscatter
render_jscatter class
Reactively render a jupyter-scatter scatter plot.
Usage Source
render_jscatter(
_fn: Optional[ValueFn[ValueT]] = None,
*,
width: Optional[str] = None,
height: Optional[str] = None,
fill: Optional[bool] = None,
fillable: Optional[bool] = None,
rate_policy: Optional[RatePolicy] = None,
rate_delay: Optional[float] = None,
)@render_jscatter is a decorator that creates a render function – a function that returns the plot to display and re-runs when the reactive values it reads change:
import pandas as pd
from jscatter import Scatter
from shinywidgets import render_jscatter
df = pd.DataFrame({"x": [1, 2, 3], "y": [1, 4, 9]})
@render_jscatter
def plot():
return Scatter(data=df, x="x", y="y")The render function may return a jscatter.Scatter (which is coerced to its jscatter.widget.JupyterScatter widget; requires pip install 'shinywidgets[jscatter]') or a JupyterScatter widget. The plot is resized to fit its output, whether the output fills its layout or has an explicit height (see below), unless the plot has a height of its own (e.g., from Scatter.height(); jupyter-scatter’s default of 240 doesn’t count).
Note
Accessing the rendered widget: the render function gains two read-only attributes: .value, the value it most recently returned, and .widget, the rendered JupyterScatter instance. Widget state can also be read reactively with plot.read("some_trait") (a shortcut for reactive_read() on .widget).
Responding to user interaction: read plot.selected() in a reactive function (a @render.* function, @reactive.calc, or @reactive.effect), which re-runs whenever the user selects points (with the lasso, or by clicking one), much like input.my_slider() reads an input. The selection is an array of row positions, not index labels; plot.selected_rows() returns the selected rows of the plot’s data frame instead. A re-render (e.g. when the render function reads an input) gives the user a new plot, whose selection starts out empty. It can’t be read inside this output’s own render function, which builds a new plot each time it runs. Other traits worth reading with plot.read() are "hovering" (the hovered point’s row position), "zoom_level", and "lasso_selection_polygon" (the lasso path in data coordinates).
Large selections: selecting more than about 3 million points sends the server a message larger than the default 16 MiB websocket limit. The message is dropped client-side before it can close the connection: the session stays up and the rest of the app keeps working, but the selection is lost and the user sees a sticky error notification. Raise the limit with shiny run --ws-max-size and set the SHINYWIDGETS_WS_MAX_SIZE environment variable to match (Shiny doesn’t expose its real limit to sessions, so the client enforces the env var’s value).
Mutating the widget: use .widget to update the rendered plot in place; trait changes on the widget are synced to the browser.
Parameters
width : Optional[str] = None-
A CSS length unit (e.g.,
"400px"or"100%") for the output’s width. height : Optional[str] = None-
A CSS length unit for the output’s height. When
None(the default), the output is designed to fill the height of its parent container (seefillandfillable). fill : Optional[bool] = None-
Whether the output should grow or shrink to fit its parent container. When
None(the default), this isTrueifheightis not specified. fillable : Optional[bool] = None-
Whether the output container should fill available space (scrolling its contents on overflow). When
None(the default), this isTrueifheightis not specified. rate_policy : Optional[RatePolicy] = None-
How to rate-limit
reactive_read()on the widget:"debounce"or"throttle".None(the default) debouncesreactive_read()only ifrate_delayis given. rate_delay : Optional[float] = None-
The rate-limit window in seconds (default 0.25).
0disables rate limiting. Each :which :
See also
output_widget(): in Shiny Core, the UI needs this to hold the output (Shiny Express displays it where the render function is defined).
Methods
selected() |
The currently selected points as a numpy.ndarray (uint32) of row positions into the plot’s data (use df.iloc[plot.selected()]), from a lasso or single click. |
selected_rows() |
The rows of df at the selected positions (see selected()). |
selected()
render_jscatter.selected()The currently selected points as a numpy.ndarray (uint32) of row positions into the plot’s data (use df.iloc[plot.selected()]), from a lasso or single click.
Empty while nothing is selected. Cancels (like .widget) until the browser first reports, which a bare JupyterScatter only does after the first selection. For index labels instead of positions (when the render function returns a jscatter.Scatter with data_use_index=True), use plot.value.selection(). Not rate-limited.
selected_rows()
render_jscatter.selected_rows(df: Optional[IntoDataFrameT] = None)The rows of df at the selected positions (see selected()).
df defaults to the frame the returned jscatter.Scatter was built with (Scatter(data=df, ...)); pass it when the render function returns a bare JupyterScatter (which retains no frame), or when the plot’s rows aren’t df’s rows in order. Any frame type works (pandas, polars, …); the result has the same type. Empty while nothing is selected, so it can be passed straight to @render.data_frame. Cancels until the browser first reports, like selected().
The match is positional (df.iloc[plot.selected()]), so after a re-render or in-place data replacement with different rows, a retained position can point at a different row – carry an ID column and look rows up by it when the data can change.