Putting it together

The basics of the user interface (UI) inputs and outputs enables you to start building dynamic dashboards and applications. On this page, we’ll walk through 2 examples.

example covers
CSV parser Enter text, see the resulting pandas DataFrame
Plot traits for dog breeds (e.g. drooliness) Select dog breeds and traits to compare

Since the examples load the pandas library, it may take some time to load the apps on this page.

Example 1: parsing and displaying CSV

In this example, we’ll parse CSV data users paste in, and display it as a table.

Note that to do this, we need to use a little bit of code to allow the pandas to read a string of text:

#| components: [editor, cell]

import pandas as pd
from io import StringIO

csv_text = """


The key is that .read_csv() expects a file. StringIO() takes the text and makes it into something file-like that .read_csv() understands.

Below, we include this snippet in a Shiny application, to allow users to input text.

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 200

## file: app.py

import pandas as pd
from io import StringIO

from shiny import App, render, ui

app_ui = ui.page_fluid(
    ui.input_text_area("csv_text", "CSV Text", value="a, b\n1, 2"),

def server(input, output, session):
    def parsed_data():
        file_text = StringIO(input.csv_text())
        data = pd.read_csv(file_text)
        return data

# This is a shiny.App object. It must be named `app`.
app = App(app_ui, server)

Notice that…

  • We replaced the variable csv_text with input.csv_text(), to get the user’s input.
  • We are using output_table() to display a formatted table.

Try the following to see how pandas parses different CSVs:

Extra commas


Raises a parsing error

a, b
1, 2

Example 2: Visualizing dog traits

In this example, we’ll visualize dog traits by breed. For example, the drooling level of German Shepherds.

Viewers will be able to select the following:

  • which dog breeds to see traits for.
  • which traits to plot ratings for.

Here is a preview of the data:

breed trait rating
Retrievers (Labrador) Affectionate With Family
German Shepherd Dogs Affectionate With Family
Bulldogs Affectionate With Family
Retrievers (Labrador) Good With Young Children
German Shepherd Dogs Good With Young Children
Bulldogs Good With Young Children

We’ll take inputs for breed and trait, and use them to subset the data.

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 600

## file: app.py

from shiny import App, render, ui
import pandas as pd
import seaborn as sns

from pathlib import Path


long_breeds = pd.read_csv(Path(__file__).parent / "dog_traits_long.csv")

options_traits = long_breeds["trait"].unique().tolist()
options_breeds = long_breeds["breed"].unique().tolist()

app_ui = ui.page_fluid(
    ui.input_selectize("traits", "Traits", options_traits, multiple=True),
    ui.input_selectize("breeds", "Breeds", options_breeds, multiple=True),

def server(input, output, session):
    def barchart():
        # note that input.traits() refers to the traits selected via the UI
        indx_trait = long_breeds["trait"].isin(input.traits())
        indx_breed = long_breeds["breed"].isin(input.breeds())

        # subset data to keep only selected traits and breeds
        sub_df = long_breeds[indx_trait & indx_breed]
        sub_df["dummy"] = 1

        # plot data. we use the same dummy value for x, and use hue to set
        # the bars next to eachother
        g = sns.catplot(
            data=sub_df, kind="bar",
            y="rating", x="dummy", hue="trait",
            col="breed", col_wrap=3,

        # remove labels on x-axis, which is on the legend anyway

        return g

app = App(app_ui, server)

## file: dog_traits_long.csv
Retrievers (Labrador),Affectionate With Family,5
French Bulldogs,Affectionate With Family,5
German Shepherd Dogs,Affectionate With Family,5
Retrievers (Golden),Affectionate With Family,5
Bulldogs,Affectionate With Family,4
Poodles,Affectionate With Family,5
Beagles,Affectionate With Family,3
Rottweilers,Affectionate With Family,5
Retrievers (Labrador),Good With Young Children,5
French Bulldogs,Good With Young Children,5
German Shepherd Dogs,Good With Young Children,5
Retrievers (Golden),Good With Young Children,5
Bulldogs,Good With Young Children,3
Poodles,Good With Young Children,5
Beagles,Good With Young Children,5
Rottweilers,Good With Young Children,3
Retrievers (Labrador),Good With Other Dogs,5
French Bulldogs,Good With Other Dogs,4
German Shepherd Dogs,Good With Other Dogs,3
Retrievers (Golden),Good With Other Dogs,5
Bulldogs,Good With Other Dogs,3
Poodles,Good With Other Dogs,3
Beagles,Good With Other Dogs,5
Rottweilers,Good With Other Dogs,3
Retrievers (Labrador),Shedding Level,4
French Bulldogs,Shedding Level,3
German Shepherd Dogs,Shedding Level,4
Retrievers (Golden),Shedding Level,4
Bulldogs,Shedding Level,3
Poodles,Shedding Level,1
Beagles,Shedding Level,3
Rottweilers,Shedding Level,3
Retrievers (Labrador),Coat Grooming Frequency,2
French Bulldogs,Coat Grooming Frequency,1
German Shepherd Dogs,Coat Grooming Frequency,2
Retrievers (Golden),Coat Grooming Frequency,2
Bulldogs,Coat Grooming Frequency,3
Poodles,Coat Grooming Frequency,4
Beagles,Coat Grooming Frequency,2
Rottweilers,Coat Grooming Frequency,1
Retrievers (Labrador),Drooling Level,2
French Bulldogs,Drooling Level,3
German Shepherd Dogs,Drooling Level,2
Retrievers (Golden),Drooling Level,2
Bulldogs,Drooling Level,3
Poodles,Drooling Level,1
Beagles,Drooling Level,1
Rottweilers,Drooling Level,3
Retrievers (Labrador),Openness To Strangers,5
French Bulldogs,Openness To Strangers,5
German Shepherd Dogs,Openness To Strangers,3
Retrievers (Golden),Openness To Strangers,5
Bulldogs,Openness To Strangers,4
Poodles,Openness To Strangers,5
Beagles,Openness To Strangers,3
Rottweilers,Openness To Strangers,3
Retrievers (Labrador),Playfulness Level,5
French Bulldogs,Playfulness Level,5
German Shepherd Dogs,Playfulness Level,4
Retrievers (Golden),Playfulness Level,4
Bulldogs,Playfulness Level,4
Poodles,Playfulness Level,5
Beagles,Playfulness Level,4
Rottweilers,Playfulness Level,4
Retrievers (Labrador),Watchdog/Protective Nature,3
French Bulldogs,Watchdog/Protective Nature,3
German Shepherd Dogs,Watchdog/Protective Nature,5
Retrievers (Golden),Watchdog/Protective Nature,3
Bulldogs,Watchdog/Protective Nature,3
Poodles,Watchdog/Protective Nature,5
Beagles,Watchdog/Protective Nature,2
Rottweilers,Watchdog/Protective Nature,5
Retrievers (Labrador),Adaptability Level,5
French Bulldogs,Adaptability Level,5
German Shepherd Dogs,Adaptability Level,5
Retrievers (Golden),Adaptability Level,5
Bulldogs,Adaptability Level,3
Poodles,Adaptability Level,4
Beagles,Adaptability Level,4
Rottweilers,Adaptability Level,4
Retrievers (Labrador),Trainability Level,5
French Bulldogs,Trainability Level,4
German Shepherd Dogs,Trainability Level,5
Retrievers (Golden),Trainability Level,5
Bulldogs,Trainability Level,4
Poodles,Trainability Level,5
Beagles,Trainability Level,3
Rottweilers,Trainability Level,5
Retrievers (Labrador),Energy Level,5
French Bulldogs,Energy Level,3
German Shepherd Dogs,Energy Level,5
Retrievers (Golden),Energy Level,3
Bulldogs,Energy Level,3
Poodles,Energy Level,4
Beagles,Energy Level,4
Rottweilers,Energy Level,3
Retrievers (Labrador),Barking Level,3
French Bulldogs,Barking Level,1
German Shepherd Dogs,Barking Level,3
Retrievers (Golden),Barking Level,1
Bulldogs,Barking Level,2
Poodles,Barking Level,4
Beagles,Barking Level,4
Rottweilers,Barking Level,1
Retrievers (Labrador),Mental Stimulation Needs,4
French Bulldogs,Mental Stimulation Needs,3
German Shepherd Dogs,Mental Stimulation Needs,5
Retrievers (Golden),Mental Stimulation Needs,4
Bulldogs,Mental Stimulation Needs,3
Poodles,Mental Stimulation Needs,5
Beagles,Mental Stimulation Needs,4
Rottweilers,Mental Stimulation Needs,5

Note that:

  • We use input_selectize() with multiple=True to let users select multiple options from a dropdown.
  • We figure out the options for each input before hand, using the pandas .unique().tolist() methods.

Next up

On this page, we’ve looked at two examples of simple applications that react to changes in inputs. This just scratches the surface of what Shiny can do. In the next section, we’ll go through more advanced tools for reactive programming in Shiny.