Full tutorial from my Shiny for Python SciPy tutorial:
#| output-location: slide
from palmerpenguins import load_penguins
from plotnine import aes, geom_histogram, ggplot, theme_minimal
dat = load_penguins()
dat.head()
species = "Adelie" # selected species
sel = dat.loc[dat.species == species] # selected data
(
ggplot(aes(x="bill_length_mm"))
+ geom_histogram(dat, fill="#C2C2C4", binwidth=1)
+ geom_histogram(sel, fill="#447099", binwidth=1)
+ theme_minimal()
)#| output-location: slide
from palmerpenguins import load_penguins
from plotnine import aes, geom_histogram, ggplot, theme_minimal
dat = load_penguins()
dat.head()
species = "Gentoo" # change species
sel = dat.loc[dat.species == species]
(
ggplot(aes(x="bill_length_mm"))
+ geom_histogram(dat, fill="#C2C2C4", binwidth=1)
+ geom_histogram(sel, fill="#447099", binwidth=1)
+ theme_minimal()
)#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
# | standalone: true
# | components: [editor, viewer]
# | layout: horizontal
from shiny.express import ui
ui.input_radio_buttons(
id="species",
label="Species",
choices=["Adelie", "Gentoo", "Chinstrap"],
)https://shiny.posit.co/py/api/express/express.ui.input_radio_buttons.html
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
# | standalone: true
# | components: [editor, viewer]
# | layout: horizontal
from shiny.express import ui
ui.input_radio_buttons(
id="species",
label="Species",
choices=["Adelie", "Gentoo", "Chinstrap"],
inline=True,
)Now let’s add all that data and plotting code from earlier into our application.
If we just dump in our code, the application errors because it does not know what to do with the figure that’s trying to be printed.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
# | standalone: true
# | components: [editor, viewer]
# | layout: horizontal
from shiny.express import ui
from palmerpenguins import load_penguins
from plotnine import aes, geom_histogram, ggplot, theme_minimal
ui.input_radio_buttons(
id="species",
label="Species",
choices=["Adelie", "Gentoo", "Chinstrap"],
inline=True,
)
dat = load_penguins()
species = "Adelie"
sel = dat.loc[dat.species == species]
# this will cause a TypeError: Invalid tag item type
(
ggplot(aes(x="bill_length_mm"))
+ geom_histogram(dat, fill="#C2C2C4", binwidth=1)
+ geom_histogram(sel, fill="#447099", binwidth=1)
+ theme_minimal()
)https://shiny.posit.co/py/components/#outputs
We now need to use one of the built-in Shiny output components,
Specifically, one that can render a plotnine figure (which is based on matplotlib), plot output component.
For example, we want to return a plot, so we will need to wrap our plotnine code, and decorate it with the @render.plot decorator.
Return the output
Don’t forget to return the object you want displayed in the function! Otherwise the output will not render.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
# | standalone: true
# | components: [editor, viewer]
# | layout: horizontal
from shiny.express import ui, render
from palmerpenguins import load_penguins
from plotnine import aes, geom_histogram, ggplot, theme_minimal
ui.input_radio_buttons(
id="species",
label="Species",
choices=["Adelie", "Gentoo", "Chinstrap"],
inline=True,
)
dat = load_penguins()
species = "Adelie"
sel = dat.loc[dat.species == species]
@render.plot #<<
def plot(): #<<
return ( #<<
ggplot(aes(x="bill_length_mm"))
+ geom_histogram(dat, fill="#C2C2C4", binwidth=1)
+ geom_histogram(sel, fill="#447099", binwidth=1)
+ theme_minimal()
)But the radio buttons don’t change anything
We didn’t connect the input component to the output component
Reactivity is what makes Shiny unique
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from palmerpenguins import load_penguins
from plotnine import aes, geom_histogram, ggplot, theme_minimal
from shiny.express import input, render, ui
dat = load_penguins().dropna()
species = dat["species"].unique().tolist()
ui.input_radio_buttons("species", "Species", species, inline=True)
@render.plot
def plot():
sel = dat[dat["species"] == input.species()]
return (
ggplot(aes(x="bill_length_mm"))
+ geom_histogram(dat, fill="#C2C2C4", binwidth=1)
+ geom_histogram(sel, fill="#447099", binwidth=1)
+ theme_minimal()
)05:00
PyData Seattle. 2025. https://github.com/chendaniely/pydata-seattle-2025-llm