Using R as an educational tool: Shiny apps

How can we make teaching more appealing and interactive?

R has many functionalities, namely Shiny Apps. A Shiny application is an interactive and dynamic way of presenting the results of an R code & analysis. When it comes to teaching, rather than asking students to understand a problem by writing R code, we can go straight to illustrating the results and getting students to explore different outcomes.

I decided to create an educational tool to illustrate the optimal level of pollution given the benefits and costs of pollution. I am using the same problem that I set up in my previous blog post, including the same benefits and cost curves and graphs. The goal is to show in a Shiny app how benefits and costs change given different levels of pollution, and which the optimal level of pollution is.

Since this is my first time creating a Shiny app, I followed R studio’s Shiny app’s tutorial when writing the code. As explained in the tutorial, any Shiny app is composed of three sections: ui wherein the components to be shown are named, server wherein we specify each of the components, and a shinyApp call wherein we call the ui and server sections. When I started writing “shinyApp” in the R console, the template appeared automatically. See the template below:

library(shiny)

ui <- fluidPage(
  
  
)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

It is time to adapt the template above to write my shiny App.

I am recycling my old code, namely the same benefits, costs, marginal benefits and marginal costs functions:

B = function(x){1500*x-x^2}
D = function(x){300*x+2*x^2}
MB = function(x){1500-2*x} 
MC = function(x){300+4*x}

I want to create a Shiny App that shows:

  • a slider for the student to choose a level of pollution;
  • a table showing the benefits, costs and net benefits for different levels of pollution;
  • two graphs: the benefits and costs of pollution, and the marginal benefits and costs of pollution.

The level of pollution is denoted by x, and that will be our input variable, denoted by input$x. The output (i.e. the three objects to be displayed) are two graphs (“hist_1″, “hist_2“) and one table (“table“). They are denoted by output$hist_1, output$hist_2 and output$table.

The graphs were quite easy to produce, but the table was a bit complicated. The codes for my graphs were taken from my previous blog post. However, the values displayed in the table will depend on the level of pollution chosen by the user. I found a code excerpt to produce this table here. The trick to create this table is to create a “reactive” table, whose values depend on the input$x value chosen by the user.

This is the entire code to reproduce this shinyApp:

library(shiny)

ui <- fluidPage(
  sliderInput(inputId="x",
              label="Pollution Level",
              value = 25, min = 1, max = 750),
  tableOutput(outputId = "table"),
  plotOutput(outputId = "hist_1"),
  plotOutput(outputId = "hist_2")

  
)

server <- function(input, output) {
  
  tableData = reactiveValues(d1 = as.data.frame(matrix(nrow=2,ncol = 3)))
  
  observeEvent(input$x, {
    
    temp = tableData$d1
    names(temp)=c("Benefits","Costs","Net_Benefits")
    temp$Benefits    =1500*input$x-input$x^2 
    temp$Costs       =300*input$x+2*input$x^2
    temp$Net_Benefits=1500*input$x-input$x^2 - 300*input$x - 2*input$x^2
    
    tableData$d1 = temp
    
  })
  

  test = reactive({
    d1 = as.data.frame(matrix(nrow=2,ncol = 3))
    names(d1)=c("Benefits","Costs","Net_Benefits")
    d1$Benefits    =1500*input$x-input$x^2 
    d1$Costs       =300*input$x+2*input$x^2
    d1$Net_Benefits=1500*input$x-input$x^2 - 300*input$x - 2*input$x^2
  })
  
  output$table=renderTable({
    tableData$d1
  })
  
  observe({print(test())})        # check console output
  observe({print(tableData$d1)})  # check console output
  
  observe({print(is.data.frame(test()))
    print(is.data.frame(tableData$d1))
    
  })

  
  output$hist_1 <- renderPlot({ 

    B = function(x){1500*x-x^2}
    D = function(x){300*x+2*x^2}
    title <- "Benefit and Cost of Pollution"
    plot(B(1:1000), type='l', xlab="M", ylab="D(X) & B(X)", col="blue", 
         xlim=c(0,750), ylim=c(0,450000),lwd = 4)
    curve (D, col="aquamarine4", add=TRUE,lwd = 4)
    points(input$x, 1500*input$x-input$x^2 , cex = 2, pch = 16, col ="blue")
    points(input$x, 300*input$x+2*input$x^2, cex = 2, pch = 16, col ="aquamarine4")
    
    })
  
  output$hist_2 <- renderPlot({ 
    MB = function(x){1500-2*x} 
    MC = function(x){300+4*x}
    title <- "Marginal Benefit and Marginal Cost"
    plot(MB(1:1000), type='l', xlab="M", ylab="MD & MB", col="blue", 
         xlim=c(0,750), ylim=c(0,2000),lwd = 4) 
    curve (MC, col="aquamarine4", add=TRUE,lwd = 4)
    points(input$x, 1500-2*input$x , cex = 2, pch = 16, col ="blue")
    points(input$x, 300+4*input$x  , cex = 2, pch = 16, col ="aquamarine4")
  })
  

}

shinyApp(ui, server)

You can run this code on your own R console to run this shinyApp, or you can simply see the result of the code above here:

https://anenvironmentaleconomistsguidetor.shinyapps.io/Pollution_Level/

My goal is to let my students play around with the slider (Level of Pollution) to see what happens in the graphs and the table when the level of pollution changes. Hopefully they will understand that the net benefits of pollution change for different levels of pollution, and when they maximise this value, the marginal benefit and cost curves intersect.

If you want to use this Shiny application and not the code itself, you can share the link above with whomever you need.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s