Give life to your plots with Shiny

In the last post I wrote about model SIM, we saw how to generate the model
and how to plot the figures found in the book. While it was fun to learn how
to make these graphs it didn't add much to the existing figures because the
plots were static.

Wouldn't be cool if we could see how the plots change when changing the
exogenous variables?
We can create a web application that does that with R and
Shiny, Shiny makes it easy to create web
applications in few lines of R and to share our experiments with the rest of the
world easily, only a modern browser needed.

In this post I'll show how to make a simple application that shows how model
SIM changes when we change the exogenous variables.
You can see the final application
here.

Shiny Basics

To start using Shiny we first need to install it, so run this command in your R
console:

install.packages('shiny')

A Shiny application is composed of at least two files: ui.R and server.R.
The ui file contains the definition of the user interface while the server file
contains the server side code of our application. In the next section we will
see an example of Shiny application.

Model SIM

Do you remember model SIM from the previous post?
We are going to use it to generate the data for our interactive application.

Start by creating a directory that will contain the source files

$ mkdir model_sim_app
$ cd model_sim_app

The sim.R file contains the SIM function, I added some Roxygen
markup to make clearer what each parameter does

#' Generate the data for the SIM model.
#' 
#' @param G government expenditures
#' @param alpha consumption parameters
#' @param theta personal income tax rate
#' @param W nominal wage rate
#' @param N the number of iterations
#' @param initial.state the state at the "beginning of the world"
#' @return the simulation result
SIM <- function(G = 20, alpha = c(0.6, 0.4), theta = 0.2, W = 1,
                N = 200, initial.state = 0) {
  # Calculate steady state values once
  Y.s <- G / theta
  YD.s <- (G * (1 - theta)) / theta
  # Initialize the data frame
  data <- data.frame(Year = rep(0, N),
                     C    = rep(0, N),
                     G    = rep(0, N),
                     t    = rep(0, N),
                     N    = rep(0, N),
                     YD   = rep(0, N),
                     DHs  = rep(0, N),
                     DHh  = rep(0, N),
                     Y    = rep(0, N),
                     H    = rep(0, N),
                     V.t  = rep(0, N),
                     Y.s  = rep(Y.s, N),
                     YD.s = rep(YD.s, N))
  data[1, ] = initial.state
  start <- data[1,]$Year - 1
  # Update the data frame with the model values for each iteration
  for (i in 2:N) {
    Year <- start + i
    H_1 <- data[i-1,]$H
    Y <- (G + alpha[2] * H_1) / (1 - alpha[1] * (1 - theta))
    N <- Y / W
    t <- theta * Y
    YD <- Y - t
    DHs <- G - t
    C <- alpha[1] * YD + alpha[2] * H_1
    DHh <- YD - C
    H <- DHs + H_1
    V.t <- YD * (1 - alpha[1]) / alpha[2]
    data[i,1:11] <- c(Year, C, G, t, N, YD, DHs, DHh, Y, H, V.t)
  }
  return(data)
}

Now we are ready to start playing with Shiny, first we define the ui

library(shiny)
# Use the page with sidebar layout
shinyUI(pageWithSidebar(
  # Set the page title
  headerPanel("Model SIM"),
  # Add the sidebar
  sidebarPanel(
  ),
  # Add the main panel
  mainPanel(
  )
))

then the server

library(shiny)
# Load model SIM
source("sim.R")
# Do nothing (for now)
shinyServer(function(input, output) {
})

Start the R console from inside the model_sim_app folder, then run the
following commands

> library(shiny)
> runApp()

The last command should open your default browser at http://localhost:8100/,
where you can see an almost empty page.

We can now write the code to generate the real webpage we want

# ui.R
library(shiny)
shinyUI(pageWithSidebar(
  headerPanel("Model SIM"),
  sidebarPanel(
    sliderInput("G", "Government Expenditures (G):",
                min = 0, max = 100, value = 20),
    sliderInput("theta", "Personal Income Tax Rate (Θ):",
                min = 0, max = 1, value = 0.2, step = 0.05),
    sliderInput("alpha", "Consumption Parameters (α):",
                min = 0, max = 1, value = c(0.4, 0.6), step = 0.05),
    sliderInput("DG", "Permanent Increase in Government Expenditures (ΔG):",
                min = 0, max = 100, value = 5)
  ),
  mainPanel(
    tabsetPanel(
      tabPanel("Figure 3.1",
               plotOutput("figure.3.1"),
               p(paste("Impact on national income Y and the steady",
                       "state solution Y*, following a permanent",
                       "increase in government expenditures ΔG"))),
      tabPanel("Figure 3.2",
               plotOutput("figure.3.2"),
               p(paste("Disposable income and consumption",
                       "starting from scratch"))),
      tabPanel("Figure 3.3",
               plotOutput("figure.3.3"),
               p(paste("Wealth change and wealth level, starting from",
                       "scratch"))),
      tabPanel("Figure 3.4",
               plotOutput("figure.3.4"),
               p(paste("Evolution of wealth, target wealth, consumption",
                       "and disposable income following an increase in",
                       "government expenditures ΔG")))
    )
  )
))

I added four sliderInput inside the sidebarPanel, each one has a name,
a description and some options that set their minimum, maximum and current value.
sliderInput first argument is the input variable name, we can use this to
access the input value in the server side code, for example to access the value
of the first input we write input$G.
The mainPanel contains a tabsetPanel with four tabPanel, each tab panel
has a title and some content. plotOutput("figure.3.1") tells Shiny to display
the plot with name figure.3.1, we will see soon how to make it. The p
function just creates a p html tag with the given text.

# server.R
library(shiny)
library(ggplot2)
source("sim.R")
base.plot <- function(d) {
  ggplot(d, aes(x=Year)) +
  labs(x="", y="") +
  theme(legend.direction="horizontal", legend.position="top") +
  scale_color_hue("")
}
shinyServer(function(input, output) {
  data.after.increase <- reactive({
    first.state <- SIM(input$G,
                       c(input$alpha[2],input$alpha[1]),
                       input$theta,
                       N=100)
    # We only care about the final state
    first.state <- tail(first.state, 10)
    second.state <- SIM(input$G + input$DG,
                        c(input$alpha[2], input$alpha[1]),
                        input$theta,
                        N=200,
                        initial.state=tail(first.state, 1))
    # Combine them together(remove the first element of second.state)
    d <- rbind(first.state, tail(second.state, -1L))
    return(d)
  })
  data <- reactive({
    SIM(input$G, c(input$alpha[2], input$alpha[1], input$theta))
  })
  output$figure.3.1 <- renderPlot({
    p <- base.plot(data.after.increase()) +
      geom_line(aes(y=Y, colour="Income Y")) +
      geom_line(aes(y=Y.s, colour="Steady-State solution Y*"))
    print(p)
  })
  output$figure.3.2 <- renderPlot({
    p <- base.plot(data()) +
      geom_line(aes(y=YD, colour="Disposable Income YD")) +
      geom_line(aes(y=C, colour="Consumption C"))
    print(p)
  })
  output$figure.3.3 <- renderPlot({
    p <- base.plot(data()) +
      geom_line(aes(y=H, color="Wealth Level")) +
      geom_line(aes(y=DHh, color="Household Saving"))
    print(p)
  })
  output$figure.3.4 <- renderPlot({
    p <- base.plot(data.after.increase()) +
      geom_line(aes(y=V.t, color="Target Wealth")) +
      geom_line(aes(y=YD, color="Disposable Income")) +
      geom_line(aes(y=C, color="Consumption")) +
      geom_line(aes(y=H, color="Wealth"))
    print(p)
  })
})

This is the server side of the application, first we source the file containing
the SIM function, then we define the server logic inside the shinyServer
function. I also DRYed out the code by defining a functions that builds the
common part of all four graphs.

We wrap the SIM function call inside a reactive function, this returns
a special expression that will be re-executed only when its dependencies change.
This saves us from running the simulation if we change a parameter not used
by it, for example when we change the value of ΔG the data reactive
expression won't be re-executed.
We define outputs by assigning them to slots of the output object, notice
how we use the same names used in the ui source. Inside the renderPlot
function we generate the ggplot plot and then call print on it to display it
to the user.

As you can see making our model interactive using Shiny was really easy and now
we can play with the exogenous variables to see how the model reacts. By
deploying the
application on a web server you can share it with other people to receive
feedback on what you're doing.