Calculators and computers can be used by teachers to project functions onto a screen as if they were illustrated by skilled artists. Reactive programming can be used as well to aid a teacher’s ability to illustrate changes to functions. Readers are most likely familiar with the type of reactive programming used in spreadsheets where the value of a cell a
is determined with a formula of the form a = b + c
, such that changes to either b
or c
or both b
and c
automatically update the value in a
. This article provides an overview of how the R
package shiny
(Chang, Cheng, Allaire, Xie, & McPherson, 2017) can be used to create a reactive application that shades the area between two points of a normal distribution with parameters \(\mu\) and \(\sigma\), one way of publishing the application on the internet, and links to online references where the reader can learn more about reactive programming and Shiny apps. This article starts by expanding the code given in the R graphics cookbook, written by Chang (2013), for shading the area under a curve using the R
package ggplot2
(Wickham & Chang, 2016). Next, a brief discussion follows of how to make the code reactive to user inputs using the shiny
package. Finally, the article ends with how to host a Shiny app on the shinyapps server.
To reproduce the graphs in this article, users should have R
(R Core Team, 2017) and optionally an integrated development editor (IDE) such as RStudio
installed on their computers. Both R
(https://cran.r-project.org/) and RStudio
(https://www.rstudio.com/) are freely available for installation on Windows, Mac OS X, and Linux variants. This article assumes the reader has some familiarity with R
. If the reader needs an introduction to or a refresher on using R
, free interactive tutorials are offered by Data Camp (https://www.datacamp.com/).
The function areabetweenN()
shown below is a modification and compilation of several functions described starting on page 272 of the R graphics cookbook written by Chang (2013).
areabetweenN <- function(mu = 0, sigma = 1, min = -1, max = 1, ALPHA = 0.4, FILL = "PURPLE"){
abN <- round(pnorm(max, mu, sigma) - pnorm(min, mu, sigma), 4)
p <- ggplot(data.frame(x=c(mu - 3.5*sigma, mu + 3.5*sigma)), aes(x = x))
limitRange <- function(min = min, max = max) {
function(x) {
y <- dnorm(x, mu, sigma)
y[x < min | x > max] <- NA
return(y)
}
}
SDB <- -3:3*sigma + mu
p + stat_function(fun = dnorm, args = list(mu, sigma)) +
stat_function(fun = limitRange(min = min, max = max),
geom = "area", fill = FILL, alpha = ALPHA, n = 500) +
theme_bw(base_size = 8) +
labs(x = paste("X ~ N(", mu,",",sigma,")"), y = "",
title = paste("The area between", min, "and", max, "is", abN)) +
scale_x_continuous(breaks=SDB)
}
To show the area between 80 and 120 of a \(N(\mu = 100, \sigma = 10)\) distribution, one should enter the code shown below at the R
prompt; and the resulting graph will render as shown in Figure 3.1.
areabetweenN(mu = 100, sigma = 10, min = 80, max = 120)
The basic template for a Shiny app has three components: a user interface object, a server object, and the function shinyApp()
that combines the user interface object and the server object into a reactive application known as a Shiny app. RStudio has excellent tutorials and documentation for creating Shiny apps available at http://shiny.rstudio.com/. In addition to the tutorials at http://shiny.rstudio.com/, the shiny-cheatsheet available from https://www.rstudio.com/wp-content/uploads/2016/01/shiny-cheatsheet.pdf is a great reference document. The basic template is shown below that creates a valid, albeit empty, web page. It is the responsibility of the programmer to define the user interface and to write valid code for the server object.
# Template for shiny app
library(shiny)
ui <- fluidPage()
server <- function(input, output){}
shinyApp(ui = ui, server = server)
The user interface determines the layout for reactive inputs, while the server object specifies how R will interact with the user inputs. The code below creates a reactive application the reader can use at https://alanarnholt.shinyapps.io/Normal_Area/.
# Normal Distribution Calculator shiny app code
ui <- fluidPage(
# Application title
titlePanel("Area Between Two Values of A Normal Distribution"),
sidebarLayout(
sidebarPanel(
numericInput(inputId = "MU", label = "Mean:", value = 0, min = -Inf,
max = Inf),
numericInput(inputId = "SIGMA", label = "Standard Deviation:",
value = 1, min = 0.0000001, max = Inf),
numericInput(inputId = "MIN", label = "Lower:", value = -2, min = -Inf,
max = Inf),
numericInput(inputId = "MAX", label = "Upper:", value = 2, min = -Inf,
max = Inf),
textInput(inputId = "COLOR", label = "Color:", value = "hotpink"),
numericInput(inputId = "ALPHA", label = "Intensity:", value = 0.4,
min = 0.05, max = 1)
),
mainPanel(
plotOutput("NG", height = "500px", width = "500px")
)
))
server <- function(input, output){
library(ggplot2)
output$NG <- renderPlot({
abN <- round(pnorm(input$MAX, input$MU, input$SIGMA) -
pnorm(input$MIN, input$MU, input$SIGMA),4)
p <- ggplot(data.frame(x=c(input$MU - 3.5*input$SIGMA, input$MU + 3.5*input$SIGMA)),
aes(x = x))
limitRange <- function(min = input$MIN, max = input$MAX) {
function(x) {
y <- dnorm(x, input$MU, input$SIGMA)
y[x < input$MIN | x > input$MAX] <- NA
return(y)
}
}
SDB <- -3:3*input$SIGMA + input$MU
p + stat_function(fun = dnorm, args = list(input$MU, input$SIGMA)) +
stat_function(fun = limitRange(min = input$MIN, max = input$MAX),
geom = "area", fill = input$COLOR, alpha = input$ALPHA,
n = 500) +
theme_bw(base_size = 18) +
labs(x = paste("X ~ N(", input$MU,",",input$SIGMA,")"), y = "",
title = paste("The area between", input$MIN, "and", input$MAX, "is", abN)) +
scale_x_continuous(breaks=SDB)
})
}
shinyApp(ui = ui, server = server)
A screen shot of the application is visible in Figure 4.1.
The “Normal Distribution Calculator shiny app code” should be saved in its own directory with the name app.R
. In this example, the user interface is created with the function sidebarLayout()
that creates a sidebar occupying 1/3 of the screen and a main area occupying 2/3 of the screen. The appearance of the sidebar is determined with the sidebarPanel()
function. In this example, the sidebar has five numeric inputs and one text input. The output NG
created from the renderPlot({})
function in the server object is shown in the main panel with the plotOutput()
function. The code inside renderPlot({})
is the function areabetweenN()
with the exception that all arguments to the function areabetweenN()
are made reactive using the syntax input$par
where par
is an inputId
defined in the user interface. To change the shading color, enter a valid R
color name or a hexadecimal color such as #FF000
for red. To see all 657 R
colors names, type colors()
at the R
prompt.
To publish your own Shiny apps on the shinyapps server, you will need to create a free account at http://www.shinyapps.io/. Once your account is created, follow the directions at http://docs.rstudio.com/shinyapps.io/getting-started.html#deploying-applications to deploy your application on the shinyapps server.
Chang, W. (2013). R graphics cookbook: [Practical recipes for visualizing data] (1. ed). Beijing: O’Reilly.
Chang, W., Cheng, J., Allaire, J., Xie, Y., & McPherson, J. (2017). Shiny: Web application framework for r. Retrieved from https://CRAN.R-project.org/package=shiny
R Core Team. (2017). R: A language and environment for statistical computing. Vienna, Austria: R Foundation for Statistical Computing. Retrieved from https://www.R-project.org/
Wickham, H., & Chang, W. (2016). Ggplot2: Create elegant data visualisations using the grammar of graphics. Retrieved from https://CRAN.R-project.org/package=ggplot2