Today, we’ll introduce Shiny, which allows us to easily produce interactive webpages with R! Make sure to install and load it:
Let’s say we wanted to write an extremely simple interactive application:
The user types some text into a textbox and what they’ve entered is displayed to them.
There’s a piece of data, the input string, on which the printed text depends.
We need some system of answering these questions.
We could redraw the text from the input each frame.
Problem: this is very slow.
We should only update the text when the input has changed.
Problem: this is difficult to write and manage.
It’d be nice if we could set a variable and specify what to do when it changes without having to track the changes ourselves.
This, at a high level, is how Shiny works. Shiny is reactive, which makes our lives much easier.
Let’s explore Shiny and see what this means.
Your Shiny application will consist of two objects.
Here you define the components that make up the webpage. Some examples:
You give each a name.
Your Shiny application will consist of two objects.
Here you define the rules for how the webpage will react to changes in the component’s values.
In the UI object, you define the components of the webpage.
textInput
).textInput
takes a prompt.ui <- fluidPage(
textInput( # input component:
"text_input", # - name
"Feed me some text!" # - prompt
),
textOutput( # output component:
"text_output" # - name
)
)
server <- function(input, output, session) {
output$text_output <- renderText({
if (nChars(input$text_input) > 0) {
input$text_input
} else {
"I'm hungry!"
}
})
}
shinyApp(ui, server)
You structure the webpage by the order of nested function calls. There are additional components just for structuring the components (i.e., layout components).
The server is a function that takes input, output, and a session (don’t worry about the last).
textInput
object "text_input"
so access it with input$text_input
.renderText
, renderPlot
).ui <- fluidPage(
textInput( # input component:
"text_input", # - name
"Feed me some text!" # - prompt
),
textOutput( # output component:
"text_output" # - name
)
)
server <- function(input, output, session) {
output$text_output <- renderText({
if (nchar(input$text_input) > 0) {
input$text_input
} else {
"I'm hungry!"
}
})
}
shinyApp(ui, server)
Note that output$text_output
depends on input$text_input
.
Shiny will track this dependency for us and will update the output component whenever the input changes!
Finally, we run the application by calling shinyApp(ui, server)
.
ui <- fluidPage(
textInput( # input component:
"text_input", # - name
"Feed me some text!" # - prompt
),
textOutput( # output component:
"text_output" # - name
)
)
server <- function(input, output, session) {
output$text_output <- renderText({
if (nchar(input$text_input) > 0) {
input$text_input
} else {
"I'm hungry!"
}
})
}
shinyApp(ui, server)
The value output$text_output
was made reactive as we assigned a renderText
call to it.
The dependencies and updates are then managed by Shiny.
What if we want some variable to react to changes in input?
To do this, you instead wrap the code that determines the value in a call to the reactive
function.
server <- function(input, output, session) {
text <- reactive({
if (nchar(input$text_input) > 0) {
input$text_input
}
else {
"I'm hungry"
}
})
output$text_output <- renderText({
text() # Call the variable like a function to get its value.
})
# Now we can use this value in multiple components!
output$text_output2 <- renderText({
paste0("You entered: ", text())
})
}
Here, when text
’s dependents change, all of the outputs that depend on text
will also update.