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
bookmarkingexpanded 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