Outputs and render functions
Filling the empty boxes
All of them in one app
The same dataset, shown four ways. Change the dataset and the number of rows.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [viewer]
#| viewerHeight: 900
## file: ui.R
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
sliderInput("n", "Rows in the table:", min = 1, max = 10, value = 5)
),
mainPanel(
h4("textOutput()"),
textOutput("text"),
h4("verbatimTextOutput()"),
verbatimTextOutput("print"),
h4("tableOutput()"),
tableOutput("table"),
h4("plotOutput()"),
plotOutput("plot", height = "300px")
)
)
)
## file: server.R
library(shiny)
server <- function(input, output, session) {
output$text <- renderText({
data <- get(input$dataset)
paste("The dataset", input$dataset, "has", nrow(data), "rows and",
ncol(data), "columns.")
})
output$print <- renderPrint({
data <- get(input$dataset)
summary(data)
})
output$table <- renderTable({
data <- get(input$dataset)
head(data, input$n)
})
output$plot <- renderPlot({
data <- get(input$dataset)
plot(data[, 1:2])
})
}
Each of the four boxes in the app (a sentence, a summary, a table, a plot) is an output. Let’s see how they are made.
How an output is made
An output always comes in pairs:
- in
ui.R, a*Output()function reserves an empty box and says what kind of content it will contain - in
server.R, the matchingrender*()function produces the content and puts it in the box with the same ID
- 1
-
“Here there will be a plot, called
graph” - 2
-
Fill the box
graph, with a function that makes plots - 3
- Any R code that draws a plot
The pairs
In ui.R |
In server.R |
Shows |
|---|---|---|
textOutput() |
renderText() |
plain text, inline |
verbatimTextOutput() |
renderPrint() |
what R prints in the console |
plotOutput() |
renderPlot() |
a plot |
tableOutput() |
renderTable() |
a (small) table |
uiOutput() |
renderUI() |
new UI elements, created by the server (Your app: explore a dataset) |
downloadButton() |
downloadHandler() |
a file to download (Going further) |
The code of the app
Here is the code of the app above. Find the four pairs *Output() / render*(). You can edit it and press ▶.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 900
## file: ui.R
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
sliderInput("n", "Rows in the table:", min = 1, max = 10, value = 5)
),
mainPanel(
h4("textOutput()"),
textOutput("text"),
h4("verbatimTextOutput()"),
verbatimTextOutput("print"),
h4("tableOutput()"),
tableOutput("table"),
h4("plotOutput()"),
plotOutput("plot", height = "300px")
)
)
)
## file: server.R
library(shiny)
server <- function(input, output, session) {
output$text <- renderText({
data <- get(input$dataset)
paste("The dataset", input$dataset, "has", nrow(data), "rows and",
ncol(data), "columns.")
})
output$print <- renderPrint({
data <- get(input$dataset)
summary(data)
})
output$table <- renderTable({
data <- get(input$dataset)
head(data, input$n)
})
output$plot <- renderPlot({
data <- get(input$dataset)
plot(data[, 1:2])
})
}
get("cars") returns the object called cars: it is a quick way to go from the name of a dataset (a text, the value of the input) to the dataset itself.
renderText() or renderPrint()?
They look similar but they are not the same:
renderText()turns the result into one plain string (it usescat()): good for sentencesrenderPrint()shows the result as the R console would print it: good forsummary(),str(), models, data frames
In the app above, replace renderPrint with renderText for summary(data) (and verbatimTextOutput with textOutput in the UI): the numbers are all glued together. That is why we use renderPrint() for statistical output.
Common mistakes
- The IDs do not match:
plotOutput("graph")in the UI,output$grahpin the server. No error, just an empty box - The pair is wrong:
plotOutput()in the UI,renderPrint()in the server. The box cannot show that content - You forgot
output$...:renderPlot({ ... })alone computes the plot and throws it away - The box is not in the UI: the server fills
output$summary, butui.Rhas no...Output("summary")
Your turn
Open the code of the datasets app in the editor and add a second plot: a histogram of the first column of the dataset (hist(data[, 1])).
You need two changes: one in ui.R and one in server.R.
# ui.R, inside mainPanel()
plotOutput("hist", height = "300px")# server.R, inside the server function
output$hist <- renderPlot({
data <- get(input$dataset)
hist(data[, 1], main = names(data)[1])
})Copy the files of apps/02-datasets into your project (replacing your ui.R and server.R) and run it. We use it in the next page.