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)
No matching items

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)

No matching items

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:

  1. 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. The id parameter you provide will be used to link to other parts of the Shiny app.

  2. 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 your ui.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
  3. Decorate your plotting function with a @render.plot() decorator.

    • If your plotting function is not the same as the id you used in the ui.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.

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:.

  1. click - When click = 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 named input.<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.

  2. dblclick - This is just like the click parameter, but for double-click events. The value can be accessed as input.<id>_dblclick().

  3. hover - When hover = 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 named input.<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, set hover to hover_opts().

  4. brush - When brush = 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 named input.<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, set brush to brush_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)
No matching items