Skip to content

Instantly share code, notes, and snippets.

@trestletech
Last active August 29, 2015 14:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trestletech/629d3f2c710db719f89f to your computer and use it in GitHub Desktop.
Save trestletech/629d3f2c710db719f89f to your computer and use it in GitHub Desktop.
Slides from RStudio's presentation on Shiny at R/Finance 2014. Hosted version available here: https://trestletech.shinyapps.io/rfinance2014/an-introduction-to-rstudio-shiny.Rmd#1
.Rproj.user
.Rhistory
.RData
---
title: "An Introduction to RStudio Shiny"
author: "R/Finance 2014"
date: "Friday, May 16, 2014"
output:
ioslides_presentation:
self_contained: true
runtime: shiny
---
<style type="text/css">
slides > slide:before {
font-size: 12pt;
content: 'http://bit.ly/shinyRfin';
position: absolute;
text-align: center;
bottom: 15px;
left: 50%;
margin-left: -300px;
width: 600px;
line-height: 1.9;
}
div.img-col{
text-align: center;
font-size: 14pt;
}
a {
border-bottom: none !important;
}
.wrapper {
margin: 70px auto;
position: relative;
z-index: 90;
}
.ribbon-wrapper-green {
width: 145px;
height: 148px;
overflow: hidden;
position: absolute;
top: -3px;
right: -3px;
}
.ribbon-green {
font: bold 15px Sans-Serif;
color: #333;
text-align: center;
text-shadow: rgba(255,255,255,0.5) 0px 1px 0px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
position: relative;
padding: 7px 0;
left: -25px;
top: 45px;
width: 220px;
background-color: #7ADCBF;
background-image: -webkit-gradient(linear, left top, left bottom, from(#8AACDF), to(#658FBE));
background-image: -webkit-linear-gradient(top, #8AACDF, #658FBE);
background-image: -moz-linear-gradient(top, #8AACDF, #658FBE);
background-image: -ms-linear-gradient(top, #8AACDF, #658FBE);
background-image: -o-linear-gradient(top, #8AACDF, #658FBE);
color: #6a6340;
-webkit-box-shadow: 0px 0px 3px rgba(0,0,0,0.3);
-moz-box-shadow: 0px 0px 3px rgba(0,0,0,0.3);
box-shadow: 0px 0px 3px rgba(0,0,0,0.3);
}
.ribbon-green:before, .ribbon-green:after {
content: "";
border-top: 3px solid #00896e;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
position:absolute;
bottom: -3px;
}
.ribbon-green:before {
left: 0;
}
.ribbon-green:after {
right: 0;
}
</style>
Motivation
--------------------
<div class="columns-2">
- Analysis must be communicated
- Data scientists are modern diviners
- We sit between the tools and users
- Deliver static reports
- Impoverished perspective into analysis
<div class="img-col">
![wizaRd](wizard.jpg)
<div>Altered CC image courtesy <br /> of <a href="https://www.flickr.com/photos/mcgraths/">mcgraths</a> on flickr</div>
</div>
</div>
## Enter Shiny
```{r, echo=FALSE}
source("retirement.R")
shinyApp(ui=retirementApp$ui,
server=retirementApp$server,
options=retirementApp$options)
```
## About Shiny
- Interactive web application framework for R
- Create and share applications with others
- Open Source (GPL v3) R package
- Expects no knowledge of web technologies like HTML, CSS, or JavaScript (but you can leverage them, if you know them)
- Can create autonomous webpages, or embedded interactive widgets in rmarkdown
- A Shiny app consists of two parts: a user interface (UI) and a server.
## Example Shiny App -- `ui.R`
```r
fluidPage(
# Create a select drop-down
selectInput("region", "Region:",
choices = colnames(WorldPhones)),
# A place-holder for a plot to be created
plotOutput("phonePlot")
)
```
<hr>
```{r}
library(datasets)
head(WorldPhones, n=2)
```
## Example Shiny App -- `server.R`
```r
function(input, output) {
# Generate a plot named "phonePlot"
output$phonePlot <- renderPlot({
# Create a barplot for the selected region
barplot(WorldPhones[,input$region]*1000,
ylab = "Number of Telephones", xlab = "Year")
})
}
```
## Example Shiny App
```{r, echo=FALSE}
shinyApp(
ui = fluidPage(
selectInput("region", "Region:",
choices = colnames(WorldPhones)),
plotOutput("phonePlot")
),
server = function(input, output) {
output$phonePlot <- renderPlot({
barplot(WorldPhones[,input$region]*1000,
ylab = "Number of Telephones", xlab = "Year",
main= paste("Phones in", input$region))
})
},
options = list(height = 500)
)
```
## Examples -- Powerful UI
<a href="http://shiny.rstudio.com/gallery/update-input-demo.html">![widgets](widgets.png)</a>
<a href="http://shiny.rstudio.com/gallery/basic-datatable.html">![data tables](datatable.png)</a>
<a href="https://jcheng.shinyapps.io/superzip/">![leaflet](leaflet.png)</a>
<a href="http://spark.rstudio.com/trestletech/3dscatter/">![rgl](rgl.png)</a>
## Examples -- The Full Power of R
<div class="columns-2">
<a href="http://shiny.rstudio.com/gallery/kmeans-example.html">![kmeans](kmeans.png)</a>
<a href="http://shiny.rstudio.com/gallery/retirement-simulation.html">![retirement](retirement.png)</a>
- Simply an R package
- Existing R code can be used with Shiny
- HPC, parallel, etc.
- Can load-balance users across multiple Shiny processes (Pro only)
</div>
## Examples -- Rich Interactivity
<a href="http://shiny.rstudio.com/gallery/google-charts.html">![google vis](googlevis.png)</a>
<a href="http://shiny.rstudio.com/gallery/nvd3-line-chart-output.html">![nvd3](nvd3.png)</a>
<a href="http://ggvis.rstudio.com/">![ggvis](ggvis.png)</a>
## Examples -- Shiny Server Pro
<div class="columns-2">
<a href="http://shiny.rstudio.com/gallery/personalized-ui.html">![sales](sales.png)</a>
<a href="http://shiny.rstudio.com/gallery/authentication-and-database.html">![hflights](hflights.png)</a>
- Shiny Server OS is free and AGPL v3
Shiny Server Pro includes:
- Authentication (LDAP, Active Directory, Google, etc.)
- Scaling across multiple processes
- Administrative dashboard for monitoring
- Security with SSL
- Priority support
</div>
<div class="ribbon-wrapper-green"><div class="ribbon-green">RStudio Pro, too!</div></div>
## Additional Resources
- Shiny Developer Center - http://shiny.rstudio.com
- [Stack Overflow - "shiny" tag](http://stackoverflow.com/questions/tagged/shiny)
- ["Shiny Discuss" Mailing List](https://groups.google.com/d/forum/shiny-discuss)
- ***Come meet us!***
library(shiny)
paramNames <- c("start_capital", "annual_mean_return", "annual_ret_std_dev",
"annual_inflation", "annual_inf_std_dev", "monthly_withdrawals", "n_obs",
"n_sim")
# Define server logic required to generate and plot a random distribution
#
# Idea and original code by Pierre Chretien
# Small updates by Michael Kapler
#
simulate_nav <- function(start_capital = 2000000, annual_mean_return = 5.0,
annual_ret_std_dev = 7.0, annual_inflation = 2.5,
annual_inf_std_dev = 1.5, monthly_withdrawals = 1000,
n_obs = 20, n_sim = 200) {
#-------------------------------------
# Inputs
#-------------------------------------
# Initial capital
start.capital = start_capital
# Investment
annual.mean.return = annual_mean_return / 100
annual.ret.std.dev = annual_ret_std_dev / 100
# Inflation
annual.inflation = annual_inflation / 100
annual.inf.std.dev = annual_inf_std_dev / 100
# Withdrawals
monthly.withdrawals = monthly_withdrawals
# Number of observations (in Years)
n.obs = n_obs
# Number of simulations
n.sim = n_sim
#-------------------------------------
# Simulation
#-------------------------------------
# number of months to simulate
n.obs = 12 * n.obs
# monthly Investment and Inflation assumptions
monthly.mean.return = annual.mean.return / 12
monthly.ret.std.dev = annual.ret.std.dev / sqrt(12)
monthly.inflation = annual.inflation / 12
monthly.inf.std.dev = annual.inf.std.dev / sqrt(12)
# simulate Returns
monthly.invest.returns = matrix(0, n.obs, n.sim)
monthly.inflation.returns = matrix(0, n.obs, n.sim)
monthly.invest.returns[] = rnorm(n.obs * n.sim, mean = monthly.mean.return, sd = monthly.ret.std.dev)
monthly.inflation.returns[] = rnorm(n.obs * n.sim, mean = monthly.inflation, sd = monthly.inf.std.dev)
# simulate Withdrawals
nav = matrix(start.capital, n.obs + 1, n.sim)
for (j in 1:n.obs) {
nav[j + 1, ] = nav[j, ] * (1 + monthly.invest.returns[j, ] - monthly.inflation.returns[j, ]) - monthly.withdrawals
}
# once nav is below 0 => run out of money
nav[ nav < 0 ] = NA
# convert to millions
nav = nav / 1000000
return(nav)
}
plot_nav <- function(nav) {
layout(matrix(c(1,2,1,3),2,2))
palette(c("black", "grey50", "grey30", "grey70", "#d9230f"))
# plot all scenarios
matplot(nav,
type = 'l', lwd = 0.5, lty = 1, col = 1:5,
xlab = 'Months', ylab = 'Millions',
main = 'Projected Value of Initial Capital')
# plot % of scenarios that are still paying
p.alive = 1 - rowSums(is.na(nav)) / ncol(nav)
plot(100 * p.alive, las = 1, xlab = 'Months', ylab = 'Percentage Paying',
main = 'Percentage of Paying Scenarios', ylim=c(0,100))
grid()
last.period = nrow(nav)
# plot distribution of final wealth
final.nav = nav[last.period, ]
final.nav = final.nav[!is.na(final.nav)]
if(length(final.nav) == 0) return()
plot(density(final.nav, from=0, to=max(final.nav)), las = 1, xlab = 'Final Capital',
main = paste0('Distribution of Final Capital\n', 100 * p.alive[last.period], '% are still paying'))
grid()
}
renderInputs <- function(prefix) {
wellPanel(
fluidRow(
column(6,
sliderInput(paste0(prefix, "_", "n_obs"), "Number of observations (in Years):", min = 0, max = 40, value = 20),
sliderInput(paste0(prefix, "_", "start_capital"), "Initial capital invested :", min = 100000, max = 10000000, value = 2000000, step = 100000, format="$#,##0", locale="us"),
sliderInput(paste0(prefix, "_", "annual_mean_return"), "Annual investment return (in %):", min = 0.0, max = 30.0, value = 5.0, step = 0.5),
sliderInput(paste0(prefix, "_", "annual_ret_std_dev"), "Annual investment volatility (in %):", min = 0.0, max = 25.0, value = 7.0, step = 0.1)
),
column(6,
sliderInput(paste0(prefix, "_", "annual_inflation"), "Annual inflation (in %):", min = 0, max = 20, value = 2.5, step = 0.1),
sliderInput(paste0(prefix, "_", "annual_inf_std_dev"), "Annual inflation volatility. (in %):", min = 0.0, max = 5.0, value = 1.5, step = 0.05),
sliderInput(paste0(prefix, "_", "monthly_withdrawals"), "Monthly capital withdrawals:", min = 1000, max = 100000, value = 10000, step = 1000, format="$#,##0", locale="us",),
sliderInput(paste0(prefix, "_", "n_sim"), "Number of simulations:", min = 0, max = 2000, value = 200)
)
)
)
}
retirementApp <- list(
ui = fluidPage(theme="simplex.min.css",
tags$style(type="text/css",
"label {font-size: 12px;}",
".recalculating {opacity: 1.0;}"
),
fluidRow(
column(6, renderInputs("a")),
column(6,
plotOutput("a_distPlot", height = "400px")
)
),
hr(),
p("An adaptation of the",
tags$a(href="http://glimmer.rstudio.com/systematicin/retirement.withdrawal/", "retirement app"),
"from",
tags$a(href="http://systematicinvestor.wordpress.com/", "Systematic Investor"), ".")
),
server = function(input, output, session) {
getParams <- function(prefix) {
input[[paste0(prefix, "_recalc")]]
params <- lapply(paramNames, function(p) {
input[[paste0(prefix, "_", p)]]
})
names(params) <- paramNames
params
}
# Function that generates scenarios and computes NAV. The expression
# is wrapped in a call to reactive to indicate that:
#
# 1) It is "reactive" and therefore should be automatically
# re-executed when inputs change
#
navA <- reactive(do.call(simulate_nav, getParams("a")))
navB <- reactive(do.call(simulate_nav, getParams("b")))
# Expression that plot NAV paths. The expression
# is wrapped in a call to renderPlot to indicate that:
#
# 1) It is "reactive" and therefore should be automatically
# re-executed when inputs change
# 2) Its output type is a plot
#
output$a_distPlot <- renderPlot({
plot_nav(navA())
})
output$b_distPlot <- renderPlot({
plot_nav(navB())
})
},
options = list(height = 500)
)
Version: 1.0
RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default
EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX
<style type="text/css">
slides > slide:before {
font-size: 12pt;
content: 'http://bit.ly/shinyRfin';
position: absolute;
text-align: center;
bottom: 15px;
left: 50%;
margin-left: -300px;
width: 600px;
line-height: 1.9;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment