This is an R Markdown document created with examples of how to work with Shiny. Based on Coursera’s Data Products course.
It is a platform for creating simple interactive R programs embedded into a web page
A Shiny project is a directory containing at least two parts:
Example:
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Data science FTW!"),
sidebarPanel(
h3('Sidebar text')
),
mainPanel(
h3('Main Panel text')
)
))
shinyServer(
function(input, output) {
}
)
Now to run the app all you have to do is go to the directory (say, s_project) where you have the ui.R and server.R files and type runApp()
setwd("./s_project")
runApp()
You will obtain something like this:
Ok, that’s as simple as it gets. What might we want to do more than absolute simplicity?
shinyUI(pageWithSidebar(
headerPanel("Illustrating markup"),
sidebarPanel(
h1('Sidebar panel'),
h1('H1 text'),
h2('H2 Text'),
h3('H3 Text'),
h4('H4 Text')
),
mainPanel(
h3('Main Panel text'),
code('x=c(1, 2, 3)
y=cos(x)
plot(x, y)'),
p('some ordinary text')
)
))
This is what you will obtain (again, remember you need a folder with ui.R and server.R. Set your working directory to that folder and run runApp()):
Mind you it is possible to only display the sidebar panel if you leave out the instructions (the five lines between the parenthesis) after mainPanel(,
The codes to obtain that are:
shinyUI(
pageWithSidebar(
# Application title
headerPanel("Diabetes prediction"),
sidebarPanel(
numericInput('glucose', 'Glucose mg/dl', 90, min = 50, max = 200, step = 5),
submitButton('Submit')
),
mainPanel(
h3('Results of prediction'),
h4('You entered'),
verbatimTextOutput("inputValue"),
h4('Which resulted in a prediction of '),
verbatimTextOutput("prediction")
)
)
)
and
diabetesRisk <- function(glucose) glucose / 200
shinyServer(
function(input, output) {
output$inputValue <- renderPrint({input$glucose})
output$prediction <- renderPrint({diabetesRisk(input$glucose)})
}
)
The code is the following:
shinyServer(
function(input, output) {
output$oid1 <- renderPrint({input$id1})
output$oid2 <- renderPrint({input$id2})
output$odate <- renderPrint({input$date})
}
)
shinyUI(pageWithSidebar(
headerPanel("Illustrating inputs"),
sidebarPanel(
numericInput('id1', 'Numeric input, labeled id1', 0, min = 0, max = 10, step = 1),
checkboxGroupInput("id2", "Checkbox",
c("Value 1" = "1",
"Value 2" = "2",
"Value 3" = "3")),
dateInput("date", "Date:")
),
mainPanel(
h3('Illustrating outputs'),
h4('You entered'),
verbatimTextOutput("oid1"),
h4('You entered'),
verbatimTextOutput("oid2"),
h4('You entered'),
verbatimTextOutput("odate")
)
))
The code is the following:
library(UsingR)
data(galton)
shinyServer(
function(input, output) {
output$newHist <- renderPlot({
hist(galton$child, xlab='child height', col='lightblue',main='Histogram')
mu <- input$mu
lines(c(mu, mu), c(0, 200),col="red",lwd=5)
mse <- mean((galton$child - mu)^2)
text(63, 150, paste("mu = ", mu))
text(63, 140, paste("MSE = ", round(mse, 2)))
})
}
)
)
shinyUI(pageWithSidebar(
headerPanel("Example plot"),
sidebarPanel(
sliderInput('mu', 'Guess at the mean',value = 70, min = 62, max = 74, step = 0.05,)
),
mainPanel(
plotOutput('newHist')
)
))
runApprunAppTo see how this works, first type
x=1000
and then run the following app:
library(shiny)
x <<- x+ 1
y <<- 0
shinyServer(
function(input, output) {
y <<- y+ 1
output $text1 <- renderText ({input $text1})
output $text2 <- renderText ({input $text2})
output $text3 <- renderText ({as.numeric (input$text1 )+1})
output $text4 <- renderText (y)
output $text5 <- renderText (x)
}
)
shinyUI(pageWithSidebar(
headerPanel( "Hello Shiny!"),
sidebarPanel(
textInput(inputId= "text1" , label = "Input Text1" ),
textInput(inputId= "text2" , label = "Input Text2" )
),
mainPanel(
p('Output text1'),
textOutput( 'text1'),
p('Output text2'),
textOutput( 'text2'),
p('Output text3'),
textOutput( 'text3'),
p('Outsidetext'),
textOutput( 'text4'),
p('Inside text, but non-reactive'),
textOutput( 'text5')
)
))
You will obtain something like:
where you can see x+1 (remember you input x=1000) and y=1 (look inside server.R; y starts at 0 but is incremented inside shinyServer). Now note that:
All the rendertext’s in shinyServer reacted and updated the outputs in shinyUI. But now if you click refresh (top right, such as in the next picture), the value of y gets updated.
By the way, if you want to see all the magic happening while looking at where in the code it is happening, try running:
runApp(display.mode="showcase")
You’ll be able to see the code at the same time as the app is running (see next figure). If that ain’t cool, I don’t know what is…
Now, in some occasions you might want to accelerate your app, notably in the case in which the same computation is made for 2 different outputs. Imagine you have an app that takes one number x as input and outputs 2x and 2x+1. That’s pretty simple to do:
library(shiny)
shinyServer(
function(input, output) {
output $text1 <- renderText ({2*as.numeric(input$text1) })
output $text2 <- renderText ({2*as.numeric(input$text1)+1})
}
)
shinyUI(pageWithSidebar(
headerPanel( "Hello Shiny!"),
sidebarPanel(
textInput(inputId= "text1" , label = "Input Text1" )
),
mainPanel(
p('Output text1'),
textOutput( 'text1'),
p('Output text2'),
textOutput( 'text2')
)
))
If you run this app and input 5, you will obtain something like:
Now notice that you are computing the same quantity (2x) for both output$text1 and output$text2. If you want to pre-compute 2x before assigning it to output\(text1 and output\)text2, you can use the reactive function:
library(shiny)
shinyServer(
function(input, output) {
x <- reactive ({ 2*as.numeric (input$text1 )})
output $text1 <- renderText ({x() })
output $text2 <- renderText ({x()+1})
}
)
The app will work the same, but a bit faster because you pre-computed something. Of course the difference is not great in this toy example…
Something else you might want to do is to control which reactive elements are to happen immediately or which should wait for a button to be pushed. Say you want a situation where as soon as the user enters his input immediately they are displayed as output, but their sum will only be displayed as output after a button is pushed:
In the figure above, if the user presses the go button, a “5” will appear in the Output text 3. How to have that control? You have to use the isolate function:
shinyServer(
function(input, output) {
output$text1 <- renderText ({input$text1})
output$text2 <- renderText ({input$text2})
output$text3 <- renderText ({
input$goButton
isolate(as.numeric(input$text1)+as.numeric(input$text2)) # isolate makes this instruction depend on the goButton
})
}
)
shinyUI(pageWithSidebar(
headerPanel( "Hello Shiny!"),
sidebarPanel(
textInput(inputId= "text1" , label = "Input Text1" ),
textInput(inputId= "text2" , label = "Input Text2" ),
actionButton( "goButton" , "Go!")
),
mainPanel(
p('Output text1'),
textOutput( 'text1'),
p('Output text2'),
textOutput( 'text2'),
p('Output text3'),
textOutput( 'text3')
)
))
This is cool. Or you can use a conditional statement:
shinyServer(
function(input, output) {
output$text1 <- renderText ({input$text1})
output$text2 <- renderText ({input$text2})
output$text3 <- renderText ({
if (input $goButton == 0) "You have not pressed the button"
else if (input $goButton == 1) "you pressed it once"
else "OK quit pressing it"
})
}
)
which of course will give you something a bit different (but it’s easy to see what…).
Create interactive documents: http://rmarkdown.rstudio.com/authoring_shiny.html
library(shiny)
## Warning: package 'shiny' was built under R version 3.0.3
shinyApp(
ui = fluidPage(
selectInput("region", "Region:",
choices = colnames(WorldPhones)),
plotOutput("phonePlot")
),
server = function(input, output) {
output$phonePlot <- renderPlot({
barplot(WorldPhones[,input$region]*1000,
ylab = "Number of Telephones", xlab = "Year")
})
},
options = list(height = 500)
)