The use of updateSelectInput() with Shiny: Hotel Data Visualisation
Published Apr 21, 2024 by Michael Grogan
Shiny provides ample opportunity to create dynamic visualisations by allowing a user to manipulate a range of inputs, such as sliders and dropdown menus.
However, there are instances where an application needs to allow for selection of an input based on a change in another input.
For instance, let us suppose that one wishes to create a dynamic bubble chart visualisation in plotly, whereby the user designates the variables to represent X, Y and bubble size on the chart.
Now, let us also suppose that we would also like to allow the user to select between data frames to ultimately choose the appropriate data to display in the plot. This means that when an appropriate data frame is selected, the dropdown menus to select the x, y, and bubble size variables will also need to be updated depending on the selected data frame.
Let us see how this can be accomplished using updateSelectInput()
.
Learn More
Are you interested in learning more about how Shiny visualisations can be used to analyse business data more effectively?
Context
In this example, we will use Shiny to visualize publicly released earnings data for three major hotels: Hilton Worldwide Holdings, Hyatt Hotels, and Marriott International.
Specifically, we will design an interactive bubble chart using plotly to visualize brand performance across key metrics for this industry, including ADR (average daily rate), RevPAR (revenue per available room), occupancy, and number of rooms.
Creating a dynamic visualisation using Shiny and plotly in this manner can allow for comparison of hotel brands across these metrics - and allow the user flexibility in visualising brand characteristics, e.g. identifying hotel brands with favourable metrics such as high ADR and occupancy rates.
Dashboard Overview
Here is an overview of the Shiny dashboard that we will create in this instance:
In the dashboard, we can see that the user selects the Name of hotel, along with the legend (or brands that correspond to the hotel chosen).
However, we also need the X , Y, and Bubble Size variables to change depending on the hotel selected, i.e. if we select “Hyatt” under the Name of hotel dropdown, then the variables must correspond to the data associated with Hyatt.
To start building the Shiny app, the relevant libraries are imported, values and name lists are defined, and the appropriate data frame is created:
library(shiny)
library(plotly)
<- paste(c('Hilton', 'Hyatt', 'Marriott'))
values1
=c('revpar_hilton', 'adr_hilton', 'occupancy_hilton', 'rooms_hilton')
names_hilton=c('revpar_hyatt', 'adr_hyatt', 'occupancy_hyatt', 'rooms_hyatt')
names_hyatt=c('revpar_marriott', 'adr_marriott', 'occupancy_marriott', 'rooms_marriott')
names_marriott<-c("Waldorf Astoria Hotels & Resorts","LXR Hotels & Resorts","Conrad Hotels & Resorts","Canopy by Hilton","Hilton Hotels & Resorts","Curio Collection by Hilton","DoubleTree by Hilton","Tapestry Collection by Hilton","Embassy Suites by Hilton","Hilton Garden Inn","Hampton by Hilton","Tru by Hilton","Homewood Suites by Hilton","Home2 Suites by Hilton")
A<-c("Andaz", "Grand Hyatt", "Park Hyatt", "The Unbound Collection by Hyatt", "Hyatt Centric", "Hyatt Regency", "JdV by Hyatt", "Hyatt House", "Hyatt Place","NA","NA","NA","NA","NA")
B<-c("JW Marriott", "The Ritz-Carlton", "W Hotels", "Marriott Hotels", "Sheraton", "Westin", "Courtyard", "Residence Inn", "Fairfield by Marriott","NA","NA","NA","NA","NA")
C
<- list('Hilton' = names_hilton, 'Hyatt' = names_hyatt, 'Marriott' = names_marriott)
names_list
<-c(515.05,539.47,312.61,220.43,187.14,232.65,139.91,178.06,175.16,143.17,126.36,122.66,153.26,135.94)
adr_hilton<-c(334.05,266.21,237.23,156.35,128.33,161.05,93.34,117.79,121.75,96.69,86.68,81.39,115.12,100.61)
revpar_hilton<-c(64.9,49.3,75.9,70.9,68.6,69.2,66.7,66.1,69.5,67.5,68.6,66.4,75.1,74.0)
occupancy_hilton<-c(9840,1774,16950,6940,226015,31000,154708,14719,61844,149130,327690,24755,61624,75069)
rooms_hilton
<-c(348.21,242.29,442.06,255.00,225.96,194.18,214.87,161.45,145.15,NA,NA,NA,NA,NA)
adr_hyatt<-c(248.57,169.52,304.03,152.55,169.01,126.24,140.94,114.06,98.59,NA,NA,NA,NA,NA)
revpar_hyatt<-c(71.4,70.0,68.8,59.8,74.8,65.0,65.6,70.6,67.9,NA,NA,NA,NA,NA)
occupancy_hyatt<-c(7132,32506,8372,8295,11888,98544,9517,19154,62848,NA,NA,NA,NA,NA)
rooms_hyatt
<-c(307.46,494.40,331.27,205.71,182.40,227.72,157.81,165.14,129.24,NA,NA,NA,NA,NA)
adr_marriott<-c(209.27,317.65,214.88,130.26,111.56,150.71,102.04,119.27,83.72,NA,NA,NA,NA,NA)
revpar_marriott<-c(68.1,64.2,64.9,63.3,61.2,66.2,64.7,72.2,64.8,NA,NA,NA,NA,NA)
occupancy_marriott<-c(39129,30200,18454,114192,83646,46701,52769,12973,11289,NA,NA,NA,NA,NA)
rooms_marriott
<-data.frame(revpar_hilton,adr_hilton,occupancy_hilton,rooms_hilton,revpar_hyatt,adr_hyatt,occupancy_hyatt,rooms_hyatt,revpar_marriott,adr_marriott,occupancy_marriott,rooms_marriott) data
Given that the variables for Hilton contain the most observations, we are simply appending an “NA” value to those with less observations. Now, we will design the UI and server for the application.
User Interface
When using Shiny, we need to create both a user interface and a server which interact in order to create the application.
Let us firstly design the user interface of our Shiny application. Similar to the manner in which we designed the Dash application, we would like our dashboard to display:
A title
A description of our application and what it does
A link to the original earnings report
Dropdown menus to select the appropriate variables
We can implement this as follows:
<- fluidPage(
ui h1('Hotel Metrics: Q4 2023'),
h4('The purpose of this visualisation is to allow users to analyse key hotel KPIs across major hotel brands. Data sourced from relevant quarterly earnings reports.'),
h5('ADR = Average Daily Rate, RevPAR = Revenue per available room.'),
h5(''),
a("Hilton Worldwide Holdings Q4 2023 earnings data", href="https://ir.hilton.com/~/media/Files/H/Hilton-Worldwide-IR-V3/quarterly-results/2024/q4-2023-earnings-release.pdf"),
h5(''),
a("Hyatt Hotels Q4 2023 earnings data", href="https://investors.hyatt.com/files/doc_financials/2023/q4/Final-Q4-2023-Earnings-Release-Full.pdf"),
h5(''),
a("Marriott International Q4 2023 earnings data", href="https://marriott.gcs-web.com/static-files/fab13bad-9342-4162-b392-d5a1cba1403f"),
h5(''),
sidebarPanel(
selectInput("value",
"Name of hotel",
values1,selected = 'Hilton', multiple = F),
selectInput("brand", "Legend (indicating brand - must match with name of hotel)", choices = c('Hilton'='A', 'Hyatt'='B', 'Marriott'='C'), selected = 'A'),
selectInput("xcol", "X Variable", names_list['Hilton'], multiple = F),
selectInput("ycol", "Y Variable", names_list['Hilton'], multiple = F),
selectInput("sizecol", "Bubble Size", names_list['Hilton'], multiple = F),
selected = names(data)[[2]]),
mainPanel(
plotlyOutput('plot')
) )
In the above, we have created a dashboard with appropriate titles, dropdown menus, and instructed the UI to display the plot generated by plotly.
Server
Now, we will create the server. This is where we define our reactive variables in the dropdown menus - i.e. instruct the plot_ly
graph to assume the variables that are specified in those menus and modify the bubble chart accordingly.
<- function(input, output, session) {
server
observe({
updateSelectInput(session,
'xcol',
choices = names_list[input$value],
selected = names_list[input$value][1])
})
observe({
updateSelectInput(session,
'ycol',
choices = names_list[input$value],
selected = names_list[input$value][1])
})
observe({
updateSelectInput(session,
'sizecol',
choices = names_list[input$value],
selected = names_list[input$value][1])
})
<- reactive({
brand <- get(input$brand)
x
})
<- reactive({
x $xcol]
data[,input
})
<- reactive({
y $ycol]
data[,input
})
<- reactive({
size $sizecol]
data[,input
})
$plot <- renderPlotly(
output<- plot_ly(
p x = x(),
y = y(),
type = 'scatter',
mode = 'markers',
size = size(),
color = ~brand(),
colors = 'Paired',
marker = list(opacity = 0.5, sizemode = 'diameter')))
}
To break down what is happening in the above:
- updateSelectInput() is being used to update the values that are being selected under the dropdown menus. e.g. if Hyatt is selected as the name of hotel - then the variables corresponding to Hyatt will be displayed in the other relevant dropdown menus, i.e.
revpar_hyatt,adr_hyatt,occupancy_hyatt,rooms_hyatt
. - The bubble chart generated using plotly is updated to display the relevant data.
- The selection of brands under the Legend dropdown then displays the different brands corresponding to each hotel by colour.
Upon creating the server, we now create the app itself using both the ui and server elements:
shinyApp(ui,server)
Now, we can publish our newly created application to generate the below (click to enlarge):
The full code for generating the above visualisation can be found here.
To view the published web application, please click here.
Conclusion
In this article, you have seen how to create a bubble chart visualization using plotly, and then deploy this visualization as a reactive web application using both Dash and Shiny.
Moreover, you have also seen how updateSelectInput()
updates values of subsequent dropdown menus when a specific value in the initial dropdown menu is modified.
Many thanks for reading, and you can find the code materials as well as other relevant references below. If you would like to learn more about how Shiny visualisations can be used to analyse business data more effectively, please book a free 30 minute consultation with me on Calendly.