# shiny basic framework
library(shiny)
shinyApp(
ui = ,
server = function(input, output){
}
)Anatomy of Shiny Apps (from Mine Çetinkaya-Rundel, Shiny Short Course)
The Shiny app below allows us to visualise the expression \(x^n\) with n ranging from 1 to 5:
# shiny example 1
shinyApp(
ui = fluidPage(
sliderInput(inputId = "exponent",
label = "Exponent",
min = 1,
max = 5,
value = 2),
plotOutput("curvePlot")
),
server = function(input, output){
output$curvePlot <- renderPlot(
curve(x^input$exponent, from = -5, to = 5)
)
}
)ShinyApp Widget Gallery Website
print(input$vars) which vars is the input ID inside of render* functions to debug and troubleshootshinyApp(
ui = fluidPage(
selectInput("exponent", label = "Exponent",
choices = 1:5,
selected = 2),
plotOutput("curvePlot")
),
server = function(input, output){
output$curvePlot <- renderPlot(
print(input$exponent) # to see the error of selectInput turning to String. Therefore, (below)
curve(x^as.numeric(input$exponent), from = -5, to = 5) # (from above) we must use as.numeric here
)
}
)i.e. the controls which are dependent on one another.
renderUI to create a slider dependent on server-side valuesDisplay UI elements with uiOutput
UI elements are displayed before their values are set, which can lead to errors. Thus, \(\Longrightarrow\) To prevent output being shown before UI elements have values
if (is.null(input$xlim)){
return()
}1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
How to make xlim dependent? \(\Rightarrow\) We need to define the slider input inside of the server, because it's only inside of the server that your input variables exist: - decrease the size of the console, move the slider input (above, line 15-18) and add UI Output.
- output to our UI a slider which is generated service side \(\Rightarrow\) xlim_slider; inside of our server function, need to define a new output object which we'll call xlim slider, we'll assign that as the rendering of the UI object and that UI object (below, line 26-30). - prevent the errors being shown before UI elements have values (below, line 22-24).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
reactive* expression are "invalidated" when input$vars is updated. Thus, reactive expressions are only evaluated when input variables within them are updated.
Separating your code into separate reactive expressions ensures control over what is updated when we have an expensive calculation or because we are just changing the plot range for visualization, and we don't want the underlying data to change as a result of changing that variable.
Reactive objects must be called as a function.
reactive()Suppose we want to plot only a random sample of movies, of size determined by the user. What is wrong with the following?
# Server
# Create a new data frame that is a sample of n_samp
# observations from movies
movies_sample <- sample_n(movies_subset(), input$n_samp)
# Plot the sampled movies
output$scatterplot <- renderPlot({
ggplot(data = movies_sample,
aes_string(x = input$x, y = input$y, color = input$z)) +
geom_point(…)
})\(\Longrightarrow\) The solution would be:
# Server
# Create a new data frame that is a sample of n_samp
# observations from movies
movies_sample <- reactive({
req(input$n_sample) # ensure availability of value
sample(movies_sample(), input$n_sample)
})
# Plot the sampled movies
output$scatterplot <- renderPlot({
ggplot(data = movies_sample(), # need the ()
aes_string(x = input$x, y = input$y, color = input$z)) +
geom_point(…)
})render*({ [code_chunk] })
render*({ [code_chunk] }) (Shiny cheatsheet)
There are 3 different layout options available:
sidebarLayout: two column layout with responsiveness so as we move them to a mobile device rather than having two columns, we have one column which is the left hand column above the right. And this is always mapped inside of a fluidpage.
tabsetPanel: a sidebar layout with a number of different tabs in the right hand column. This is wrapped inside of a fluidpage.
navbarPage: to design multi-page applications or dashboards using Shiny App. A navbarPage is a navbarPage and not a fluidPage.
With shiny apps, it's possible to build beautiful responsive designs using numeral different layout options.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
Shiny Themes in RStudio website
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
Interface of Shiny.io
\(\Rightarrow\) Connect RStudio to shinyapps.io: - register for an account at shinyapps.io
- a free shinyapps.io account allows 25 active hours
- connect RStudio to shinyapps.io account through the Publishing section of the Global Options screen
\(\Rightarrow\) Deploying Presentations to shinyapps.io:
- ensure the preamble includes "runtime: shiny"
- "Run Presentation" \(\rightarrow\) "Publish"
\(\Rightarrow\) Manage the deployed shinyapps.io:
- must use the shinyapps.io dashboard
- track engagement and remaining active hours through the dashboard
- archive and then delete Shiny apps as necessary
Self-Contained shinyApp vs. Split-File Shiny Apps
shinyApp is useful small, self-contained Shiny apps: when we start to have large script files, it's very difficult to understand what's going on in them. \(\Rightarrow\) separating out our ui and our server components into different files, it's much easer for us to build large-scale applications and to separate our concerns.
It's also useful to note that split-file Shiny apps can be more readily reused in other content than self-contained shinyApps.
It's much easier to deploy a split-file Shiny app to the shinyapps.io service than it is a self-contained shinyApp.