Interactivity in R

Amelia McNamara

6/12/2017

manipulate package

library(manipulate)
library(ggplot2)
  • only works in RStudio
  • allows for interactive controls when coding
manipulate(
  ggplot(data=diamonds, aes(x=carat)) + geom_histogram(binwidth=binselect),
binselect = slider(min=0.5,max=1,initial=0.7, step=0.01)
)

Challenge:

Create a scatterplot of the relationship between year and girls in the arbuthnot data, with a loess smoother.

Use manipulate to add a checkbox that turns the standard error visualization on and off.

arbuthnot <- read.csv("http://www.openintro.org/stat/data/arbuthnot.csv", header=T)

Shiny

Shiny is an R package that allows you to program interactive web applications using R.

pre-Shiny quiz (warning: some of these are tricky!)

Tutorial

We’ll be going through the shiny tutorial from RStudio. The shiny cheatsheet may be helpful.

Challenge:

Create a shiny app that visualizes the same dataset three different ways.

Inspiration:

Sharing shiny apps

Shiny dashboards

Shiny dashboards are a way to have a more beautiful interface to your shiny app. They give you some nice defaults of layout.

Learning more about shiny

At the 2017 RStudio::conf there was a shiny/htmlwidgets track. All the talks are awesome! In particular:

The 2016 Shiny Developer’s Conferece went even deeper into Shiny. The videos are embedded in the site, so I can’t direct-link them, but I recommend:

  • Joe Cheng’s talk on Effective Reactive Programming
  • Jonathan McPherson on Debugging Techniques
  • Winston Chang on Profiling and Performance
  • Many of the user-submitted lightning talks are awesome, as well! In particular, check out Ricardo Bion on Using Shiny to make decisions at scale for Airbnb.

HTMLwidgets

HTMLwidgets are a way to connect any generic javascript library to R.

They’re useful because you don’t need a server to make them work– the javascript is on your local machine. So, they’re lighter-weight than shiny apps.

Some popular widgets:

Other cool stuff about HTMLwidgets

  • Crosstalk: Almost-reactive behavior, dynamic subsetting. When MassMutual folks came to talk to students at Smith about d3, they were singing the praises of Crossfilter. Crosstalk is an R implementation of Crossfilter. It allows for dynamic brushing and linking.
  • Flexdashboards are a way to make non-Shiny dashboards that are lighter-weight. They don’t have reactivity, unless it comes from a javascript library, but they don’t need a server.

Making a map with points in R with leaflet

We’re going to be doing a lot of the stuff from the RStudio leaflet tutorial.

knitr::opts_chunk$set(eval=FALSE)
library(leaflet)
m <- leaflet() %>%
  setView(-93.2650, 44.9778, zoom = 4) %>%
  addProviderTiles("Stamen.Toner") %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng=-93.2650, lat=44.9778, popup="Minneapolis!")
m

Note that the syntax here is similar to that of ggplot2. Please consult the Leaflet documentation for more details.

We need more data!!

Lets look at storm data from the NOAA. It comes in a few files that we need to join together in order to use.

library(readr)
library(dplyr)

library(RCurl)

stormlocs <- getURL("https://raw.githubusercontent.com/AmeliaMN/SummerDataViz/master/Geo/StormEvents_locations-ftp_v1.0_d2016_c20160810.csv")
stormlocs <- read_csv(stormlocs)
stormdetails <- getURL("https://raw.githubusercontent.com/AmeliaMN/SummerDataViz/master/Geo/StormEvents_details-ftp_v1.0_d2016_c20160810.csv")
stormdetails <- read_csv(stormdetails)


#stormlocs <- read_csv("StormEvents_locations-ftp_v1.0_d2016_c20160810.csv")
#stormdetails <- read_csv("StormEvents_details-ftp_v1.0_d2016_c20160810.csv")
stormlocs <- stormlocs %>%
  left_join(stormdetails, by="EVENT_ID")
lightning <- stormlocs %>%
  filter(EVENT_TYPE=="Lightning")

Mapping the lightning

Now, we can programmatically map them.

m <- leaflet(data=lightning) %>%
  addMarkers(~LONGITUDE, ~LATITUDE)

# OpenStreetMap
m %>%
  addTiles()
  
# Stamen
m %>% 
  addProviderTiles("Stamen.Toner") 

Challenge:

  • Find another storm type to map
  • Bonus– add popups!

One approach

mtw <- stormlocs %>%
  filter(EVENT_TYPE=="Marine Thunderstorm Wind")

m <- leaflet(data=mtw) %>%
  addProviderTiles("Stamen.Toner") %>% 
  addMarkers(~LONGITUDE, ~LATITUDE, popup=~EVENT_NARRATIVE)

m

Polygons

Lets start with something easy(ish) – circles

tornados <- stormlocs %>%
  filter(EVENT_TYPE=="Tornado")
m <- leaflet(data=tornados) %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addCircles(~LONGITUDE, ~LATITUDE, weight = 1, radius = ~DAMAGE_PROPERTY*100, popup = ~EVENT_NARRATIVE)
m

Polgyons come in shapefiles

Most boundaries (state, national, etc) are provided in terms of polygons. Major mapping software ArcGIS, from ESRI, has essentially set the standard formats.

Look in the GitHub repo to see some examples of how this looks. There are many files with different extensions: .prj (the projection), .shp (the shapefile), .cpg (??), .dbf (??), .shx (??).

You need special software or packages to work with shapefiles.

State shapefiles

I got these from the Census. You can choose the resolution.

If you want, the zipfile of the shapes I used is here.

We’re going to use the rgdal package to deal with shapefiles. Better would be the sp package, but I haven’t gotten there yet.

library(rgdal)

# In the Console, I need to use a different path

states <- readOGR("cb_2015_us_state_500k", layer = "cb_2015_us_state_500k", verbose = FALSE)

In RStudio, you can click on the states object to see what a Large SpatialPolygonsDataFrame looks like. @data and @polygons.

Boring, internal data from shapefile

leaflet(data=states) %>%
  addTiles() %>%
  addPolygons(stroke = FALSE, fillOpacity = 0.5, smoothFactor = 0.5, color =~colorQuantile("YlOrRd", states$AWATER)(AWATER)
  )

Something more interesting – need to count up some data

tornadocount <- tornados %>%
  group_by(STATE) %>%
  summarize(n=n())

Colors are tricky!

colorbrewer

colors <- c("#edf8fb", "#b2e2e2", "#66c2a4", "#238b45")
tornadocount <- tornadocount %>%
  mutate(color = cut(n, breaks=quantile(n)))

# Baaaaad factor practice. Do as I say, not as I do?!
levels(tornadocount$color) <- colors

Joining data

states@data$NAME <- toupper(states@data$NAME)
states@data <- left_join(states@data, tornadocount, by=c("NAME"="STATE"))

Putting it all together

leaflet(data=states) %>%
  addTiles() %>%
  addPolygons(stroke = FALSE, fillOpacity = 0.5, smoothFactor = 0.5, color = ~states@data$color.y)