Prospect Research in R/Shiny

Overview

  • What we have created at Colby
  • How we did it
  • Examples of how you can get started
  • Resources for learning more

richmajerus.com

How do we create a more data-informed organizational culture?

Quality            x            Coverage            x            Usability

Data visualization

Modern interface

Mobile optimized

Easy to use

Customizable

 

Expanded access

Where we are going next...

  • full mobile integration
  • contact reports 
  • bookmarking
  • expanded filtering

 

R is a free open-source statistical software.

RStudio is an interface to using R.

Shiny transforms R code into web applications 

How this works...

Icon made by Madebyoliver from Flaticon licensed by Creative Commons BY 3.0

Data

Application Code

Place to deploy apps

What you will need...

Database 

Data warehouse

Excel, json, csv, etc.

 

User interface code

Server code

 

Shinyapps.io 

Open source server

Professional server

RStudio Connect

 

# User Interface

library(shiny)

# Define UI
# Application that draws a histogram

shinyUI(fluidPage(

  # Application title
  titlePanel("Hello Shiny!"),

  # Sidebar with a slider input 
  # slider defines the number of bins
  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),

    # Show a plot of distribution
    mainPanel(
      plotOutput("distPlot")
    )
  )
))
# Server

library(shiny)

# Define server logic 
shinyServer(function(input, output) {

  # Expression that generates a histogram. 
  # The expression is wrapped in renderPlot 
  # This makes the plot "reactive"

  output$distPlot <- renderPlot({
    # Old Faithful Geyser data
    x    <- faithful[, 2]  
    bins <- seq(min(x), 
                max(x), 
                length.out = input$bins + 1)

    # draw the histogram 
    hist(x, 
         breaks = bins, 
         col = 'darkgray', 
         border = 'white')
  })
})

Projects to get started with...

  • Mapping

  • Query tool

  • Portfolio builder

  • Moves management dashboard

library(shiny)
library(zipcode)
library(leaflet)

# helper functions
'%ni%' <- Negate('%in%')

# load example data
example <- read.csv("example.csv", row.names = NULL)

# load zipcode data 
data(zipcode)

shinyServer(function(input, output) {
  
# read user supplied data into data()
data <- reactive({    
    # input$file1 will be NULL initially. 
    # After the user selects and uploads a file, 
    # it will be a data frame with 'name',
    # 'size', 'type', and 'datapath' columns. 
    # The 'datapath' column will contain the
    # local filenames where the data can
    # be found.
    
    inFile <- input$file1
    
    if (is.null(inFile))
      return(NULL)
    
df <- read.csv(inFile$datapath)

# clean zipcodes 
df$zip <- clean.zipcodes(df$zip)

# join lat/lon data onto user supplied data
df <- merge(df, zipcode, 
            by = 'zip', all.x = TRUE, all.y = FALSE)

return(df)
})
  

# create initial data table using supplied data 
output$contents <- DT::renderDataTable({data()}, rownames = FALSE)

# create leaflet map when users clicks create map button
observeEvent(input$plotMap, {
output$map <- renderLeaflet({
  
# cluster observations
  if(input$cluster==TRUE){
    
    leaflet(height = 3000) %>%
      #addProviderTiles("CartoDB.Positron") %>% 
      addTiles(urlTemplate = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>%
      setView(-95.396050, 39.532776, zoom = 3) %>%
       addCircleMarkers(data = data(), ~longitude, ~latitude,  
                       group = "group1", clusterOptions = markerClusterOptions()) 
  }else{
    
    leaflet(height = 3000) %>%
      #addProviderTiles("CartoDB.Positron") %>% 
      addTiles(urlTemplate = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>%
      setView(-95.396050, 39.532776, zoom = 3) %>%
      addCircleMarkers(data = data(), ~jitter(longitude, factor = .01), ~jitter(latitude, factor = .01), radius = 5, stroke = FALSE, fillOpacity = 0.5)  
    
  }
  
})
})


# create df of only obs in bounds of map
alumniInBounds <- reactive({
  
  if (is.null(input$map_bounds))
    return(data()[FALSE,])
  
  bounds <- input$map_bounds
  latRng <- range(bounds$north, bounds$south)
  lngRng <- range(bounds$east, bounds$west)
  
  subset(data(),
         latitude >= latRng[1] & latitude <= latRng[2] &
           longitude >= lngRng[1] & longitude <= lngRng[2]) 
  
})

# sum up in bounds obs for display in text
output$text <- renderUI({
  str1 <- paste(" Visible Observations:", prettyNum(nrow(alumniInBounds()), big.mark=','))
  HTML(paste(str1, sep = '<br/>'))
})


# create data table of visible obs
observeEvent(input$plotMap, {
  output$contents <- DT::renderDataTable({alumniInBounds()}, rownames = FALSE)
  })

# download example data
output$downloadData <- downloadHandler(
  filename = function() {
    paste('data-example', Sys.Date(), '.csv', sep='')
  },
  content = function(con) {
    write.csv(example, con)
  }
)
  
}) # end of server 

Server

library(shiny)
library(leaflet)

shinyUI(fluidPage(
  titlePanel("Map It"),
  
  sidebarLayout(
    sidebarPanel(width = 4,
      
      "This app allows for quick mapping of your United States data at the zipcode level.  
      Upload any file with a column called 'zip' and press the Create Map button to map your data.  
      As you zoom in the data table will adjust to display information on the visible observations.",
      
      br(),
      br(),      
      
      fileInput('file1', 'Choose CSV File',
                accept=c('text/csv', 
                         'text/comma-separated-values,text/plain', 
                         '.csv')),
      
      checkboxInput("cluster", 
                    label = "Cluster Observations", 
                    value = TRUE),
      
      actionButton("plotMap", "Create Map"), 
      
      br(),
      br(),
      
      downloadLink('downloadData', 'Download Example Data'),
      
      br(),
      br(),
      
      htmlOutput("text")  
      
    ),
    
    mainPanel(
      leafletOutput("map"), 
      br(),
      DT::dataTableOutput('contents')
    )
  )
))

User Interface

Helpful packages...

  • tidyverse
  • htmlwidgets
  • leaflet
  • highcharter
  • datatables
  • flexdashboard
  • shinydashboard

colby.edu/advancement-careers

Questions?

Links to Shiny Apps 

Public - R/Shiny for Prospect Research

By Rich Majerus

Public - R/Shiny for Prospect Research

  • 1,514