Plot (Matplotlib)
#| standalone: true
#| components: [viewer]
#| viewerHeight: 500
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from shiny import App, render, ui
app_ui = ui.page_fluid(
ui.input_slider("n", "Number of bins", 0, 100, 20),
ui.output_plot("plot"),
)
def server(input, output, session):
@render.plot(alt="A histogram")
def plot():
df = load_penguins()
mass = df["body_mass_g"]
fig, ax = plt.subplots()
ax.hist(mass, input.n(), density=True)
ax.set_title("Palmer Penguin Masses")
ax.set_xlabel("Mass (g)")
ax.set_ylabel("Density")
return fig
app = App(app_ui, server, debug=True)
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from shiny import render
from shiny.express import input, ui
ui.input_slider("n", "Number of bins", 0, 100, 20)
@render.plot(alt="A histogram")
def plot():
df = load_penguins()
mass = df["body_mass_g"]
fig, ax = plt.subplots()
ax.hist(mass, input.n(), density=True)
ax.set_title("Palmer Penguin Masses")
ax.set_xlabel("Mass (g)")
ax.set_ylabel("Density")
return fig
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from shiny import App, render, ui
app_ui = ui.page_fluid(
ui.input_slider("n", "Number of bins", 0, 100, 20),
ui.output_plot("plot"),
)
def server(input, output, session):
@render.plot(alt="A histogram")
def plot():
df = load_penguins()
mass = df["body_mass_g"]
fig, ax = plt.subplots()
ax.hist(mass, input.n(), density=True)
ax.set_title("Palmer Penguin Masses")
ax.set_xlabel("Mass (g)")
ax.set_ylabel("Density")
return fig
app = App(app_ui, server, debug=True)
Relevant Functions
-
ui.output_plot
ui.output_plot(id, width='100%', height='400px', *, inline=False, click=False, dblclick=False, hover=False, brush=False, fill=MISSING)
-
@render.plot
render.plot(_fn=None, *, alt=None, width=MISSING, height=MISSING, **kwargs)
Details
Matplotlib is a popular Python library that can be used to create plots.
Follow three steps to display a Matplotlib figure in your app:
Add
ui.output_plot()
to the UI of your app to create a div in which to display the figure. Where you call this function will determine where the figure will appear within the layout of the app. Theid
parameter you provide will be used to link to other parts of the Shiny app.Define a function within the
server()
function that creates the figure.The name of the function should be the same value you passed into the
id
parameter in yourui.output_plot()
function call in the UI.If your function calls reactive values, Shiny will update your figure whenever those values change, in a reactive fashion.
If you use
matplotlib.pyplot
to plot, your function does not need to return a value. Otherwise, your function should return one of the following objects:- A
matplotlib.figure.Figure
instance - A
matplotlib.artist.Artist
instance - A list/tuple of
Figure
/Artist
instances - An object with a ‘figure’ attribute pointing to a
matplotlib.figure.Figure
instance - A
PIL.Image.Image
instance
- A
Decorate your plotting function with a
@render.plot()
decorator.- If your plotting function is not the same as the
id
you used in theui.output_plot()
, you can add an additional@output(id=...)
decorator. - If you use the
@output()
decorator, make sure it is above the@render.plot()
decorator.
- If your plotting function is not the same as the
Plots as Inputs
You can use a plot as an input widget, collecting the locations of user clicks, double clicks, hovers, and brushes. To do this, set one or more of the following arguments of ui.output_plot()
to True
:.
click
- Whenclick = True
, the plot will allow the user to click in the plotting area, and will send the coordinates of the click to the server, where they can be accessed as a reactive variable namedinput.<id>_click()
, where<id>
is the id of the plot. The input value will be a dictionary with x and y elements indicating the mouse position.dblclick
- This is just like the click parameter, but for double-click events. The value can be accessed asinput.<id>_dblclick()
.hover
- Whenhover = True
, the plot will allow the user to hover over the plotting area, and will send the coordinates of the cursor to the server, where they can be accessed as a reactive variable namedinput.<id>_hover()
, where<id>
is the id of the plot. The input value will be a dictionary with x and y elements indicating the mouse position. To control the hover time or hover delay type, sethover
tohover_opts()
.brush
- Whenbrush = True
, the plot will allow the user to “brush” in the plotting area, and will send information about the brushed area to the server, where it can be accessed as a reactive variable namedinput.<id>_brush()
, where<id>
is the id of the plot. Brushing means that the user will be able to draw a rectangle in the plotting area and drag it around. The value will be a named list with xmin, xmax, ymin, and ymax elements indicating the brush area. To control the brush behavior, setbrush
tobrush_opts()
.
Multiple output_image()
/output_plot()
calls may share the same id value; brushing one image or plot will cause any other brushes with the same id to disappear.
Variations
Plot as input
Use the click
, dblclick
, hover
, and brush
arguments of ui.output_plot()
to collect information about the user’s mouse interactions as a reactive variable. The app below displays the values returned, but you can also call the values from within your computations to filter tables, perform calculations, and so on.
#| standalone: true
#| components: [viewer]
#| viewerHeight: 720
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from shiny import App, render, ui
app_ui = ui.page_fluid(
ui.output_plot(
"plot",
click=True,
dblclick=True,
hover=True,
brush=True,
),
"Click:",
ui.output_text_verbatim("clk", placeholder=True),
"Double Click:",
ui.output_text_verbatim("dblclk", placeholder=True),
"Hover:",
ui.output_text_verbatim("hvr", placeholder=True),
"Brush",
ui.output_text_verbatim("brsh", placeholder=True),
)
def server(input, output, session):
@render.plot(alt="A histogram")
def plot():
df = load_penguins()
mass = df["body_mass_g"]
bill = df["bill_length_mm"]
plt.scatter(mass, bill)
plt.xlabel("Mass (g)")
plt.ylabel("Bill Length (mm)")
plt.title("Penguin Mass vs Bill Length")
@render.text
def clk():
return input.plot_click()
@render.text
def dblclk():
return input.plot_dblclick()
@render.text
def hvr():
return input.plot_hover()
@render.text
def brsh():
return input.plot_brush()
app = App(app_ui, server, debug=True)
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from shiny import render
from shiny.express import input, ui
from shiny.ui import output_code, output_plot
output_plot(
"plot",
click=True,
dblclick=True,
hover=True,
brush=True,
)
"Click:"
output_code("clk", placeholder=True)
"Double Click:"
output_code("dblclk", placeholder=True)
"Hover:"
output_code("hvr", placeholder=True)
"Brush"
output_code("brsh", placeholder=True)
with ui.hold():
# Note that this Express app uses `ui.hold()` so that we can
# manually add the `output_plot()` and `output_code()` to the page.
@render.plot(alt="A histogram")
def plot():
df = load_penguins()
mass = df["body_mass_g"]
bill = df["bill_length_mm"]
plt.scatter(mass, bill)
plt.xlabel("Mass (g)")
plt.ylabel("Bill Length (mm)")
plt.title("Penguin Mass vs Bill Length")
@render.code
def clk():
return input.plot_click()
@render.code
def dblclk():
return input.plot_dblclick()
@render.code
def hvr():
return input.plot_hover()
@render.code
def brsh():
return input.plot_brush()
import matplotlib.pyplot as plt
from palmerpenguins import load_penguins
from shiny import App, render, ui
app_ui = ui.page_fluid(
ui.output_plot(
"plot",
click=True,
dblclick=True,
hover=True,
brush=True,
),
"Click:",
ui.output_text_verbatim("clk", placeholder=True),
"Double Click:",
ui.output_text_verbatim("dblclk", placeholder=True),
"Hover:",
ui.output_text_verbatim("hvr", placeholder=True),
"Brush",
ui.output_text_verbatim("brsh", placeholder=True),
)
def server(input, output, session):
@render.plot(alt="A histogram")
def plot():
df = load_penguins()
mass = df["body_mass_g"]
bill = df["bill_length_mm"]
plt.scatter(mass, bill)
plt.xlabel("Mass (g)")
plt.ylabel("Bill Length (mm)")
plt.title("Penguin Mass vs Bill Length")
@render.text
def clk():
return input.plot_click()
@render.text
def dblclk():
return input.plot_dblclick()
@render.text
def hvr():
return input.plot_hover()
@render.text
def brsh():
return input.plot_brush()
app = App(app_ui, server, debug=True)