SHINY PYTHON

Interactive visualisations

UI vs SERVER

# Here goes everything that should appear in the app and the user can interact with
app_ui = ui.page_fluid(
    # Add title
    "Emissions Aotearoa",
    # Add selection of industry to display
    #ui.input_radio_buttons("industry", "Select industry", sectors),
    ui.input_checkbox_group("industry_check", "industry", sectors),
    ui.output_plot("emission_plot"),
    # Add table
    ui.output_table("emissions_table"),
)


# Here goes everything that happens in the background: data, computations, etc...
def server(input, output, session):
    # Load dataset
    infile = Path(__file__).parent / "emissions_data_simple.csv"
    df = pd.read_csv(infile)

Preliminaries

from shiny import App, render, ui, reactive

# You can import the libraries that you need
from pathlib import Path
import pandas as pd
from matplotlib import pyplot as plt

UI - Radio buttons

# Define list/dictionary with possible sectors
sectors = ["Agriculture", "Households", "Road transport"]

# Here goes everything that should appear in the app and the user can interact with
app_ui = ui.page_fluid(
    # Add title
    "Emissions Aotearoa",
    # Add selection of industry to display
    ui.input_radio_buttons("industry_check", "Select industry", sectors)
)

Then run the app

Server - Load data

def server(input, output, session):
    # Load dataset
    
    @output
    @render.table
    def emissions_table():
      infile = Path(__file__).parent / "emissions_data_simple.csv"
      df = pd.read_csv(infile)
      return df

app = App(app_ui, server)

UI - show data

# Define list/dictionary with possible sectors
sectors = ["Agriculture", "Households", "Road transport"]

# Here goes everything that should appear in the app and the user can interact with
app_ui = ui.page_fluid(
    # Add title
    "Emissions Aotearoa",
    # Add selection of industry to display
    ui.input_radio_buttons("industry_check", "Select industry", sectors)
)

UI - show data

# Define list/dictionary with possible sectors
sectors = ["Agriculture", "Households", "Road transport"]

# Here goes everything that should appear in the app and the user can interact with
app_ui = ui.page_fluid(
    # Add title
    "Emissions Aotearoa",
    # Add selection of industry to display
    ui.input_radio_buttons("industry_check", "Select industry", sectors),
    # Add table
    ui.output_table("emissions_table")
)

Ractivity - How to make things change

Move import outside the table-creating function

# Load dataset
    infile = Path(__file__).parent / "emissions_data_simple.csv"
    df = pd.read_csv(infile)

Create a reactive element

# Load dataset
    infile = Path(__file__).parent / "emissions_data_simple.csv"
    df = pd.read_csv(infile)
# Create a reactive table for dysplaying and plotting
    df_table = reactive.Value(df)

Ractivity - How to make things change

Create a “nameless” function to update the table

    # Update the table when checkboxes are selected/unselected
    @reactive.Effect
    @reactive.event(input.industry_check)
    def _():
        # Always re-set the table to the full dataset, otherwise we break the dataframe
        df_table.set(df)
        new_val = df_table()[df_table()["anzsic_descriptor"] == input.industry_check()]     # Use this for radio buttons
        df_table.set(new_val)

Ractivity - How to make things change

Create a “nameless” function to update the table

    # Update the table when checkboxes are selected/unselected
    @reactive.Effect
    @reactive.event(input.industry_check)
    def _():
        # Always re-set the table to the full dataset, otherwise we break the dataframe
        df_table.set(df)
        new_val = df_table()[df_table()["anzsic_descriptor"] == input.industry_check()]     # Use this for radio buttons
        df_table.set(new_val)
    
    # Define table
    @output
    @render.table
    def emissions_table():
        return df_table()

Server - Add a plot

Add the following lines to the server function

# Define plot
    @output
    @render.plot
    def emission_plot():
        fig, ax = plt.subplots()
        for key, grp in df_table().groupby("anzsic_descriptor", group_keys=True):
            ax = grp.plot(ax=ax, kind='line', x="year", y="data_value", label=key, marker='o')

UI - Add a plot

Add the following line to the UI function

# Here goes everything that should appear in the app and the user can interact with
app_ui = ui.page_fluid(
    # Add title
    "Emissions Aotearoa",
    # Add selection of industry to display
    ui.input_radio_buttons("industry_check", "Select industry", sectors),
    # Add table
    ui.output_table("emissions_table"),
    # Add plot
    ui.output_plot("emission_plot")
)

Multiple selection - Checkboxes

Modify the UI function

# Here goes everything that should appear in the app and the user can interact with
app_ui = ui.page_fluid(
    # Add title
    "Emissions Aotearoa",
    # Add selection of industry to display
    #ui.input_radio_buttons("industry_check", "Select industry", sectors), # Use this for radio buttons
    ui.input_checkbox_group("industry_check", "industry", sectors),        # Use this for checkbox
    ui.output_plot("emission_plot"),
    # Add table
    ui.output_table("emissions_table")
)

Add this to the server function

def _():
    # Always re-set the table to the full dataset, otherwise we break the dataframe
    df_table.set(df)
    #new_val = df_table()[df_table()["anzsic_descriptor"] == input.industry_check()]     # Use this for radio buttons
    new_val = df_table()[df_table()["anzsic_descriptor"].isin(input.industry_check())]   # Use this for checkbox
    df_table.set(new_val)

Let’s play with it!

  • Display the mean emission for each select category
  • Give the user the ability to set the colours for the plots
  • Load the extended dataset. Let the user decide which emissions to show
  • Whatever you’d like to do