Nature, October 2014
16 June 2016
Nature, October 2014
Least squares estimation
Linear regression model
\[ y_i = \alpha + \beta x_i + \epsilon \]
Estimates for the intercept and slope can be found by minimizing the squared residuals.
\[ \arg\min_{\alpha, \beta} \sum_i \left(y_i - (\alpha + \beta x_i) \right)^2 \]
Shiny
library(shiny)
runGitHub('ekstroem/ShinyLeastSquares')
The "role" of graphics is changing and expanding
directlabels, animint, plotly, …MESS, MethComp, SuperRanker, …| Topic |
|---|
| Introduction (10 min.) |
| Interactive graphics/javascript (htmlwidgets, 30 min) |
| Interactive graphics (ggplotly/ggiraph) 20 minutes |
| Shiny 20 minutes |
| Intro to animation and direct manipulation 5 minutes |
| Basics of ggplot2 and animint 25 minutes |
| aes(showSelected), animation 25 minutes |
| aes(clickSelects), direct manipulation 25 minutes |
Tutorial goals:
CRANpackages <- c("MESS", "dplyr", "shiny", "plotly", "xts", "highcharter"
"DiagrammeR", "dygraphs", "ggplot2", "htmlwidgets",
"leaflet", "viridis")
install.packages(CRANpackages)
devtools::install_github('ramnathv/rCharts')
Or run
source("http://biostatistics.dk/useR2016pack.R")
D3.js doesn’t ship with any pre-built charts out of the box. However, go to website to get an overview of the possibilities.
Numerous possibilities in R packages
htmlwidgets Javascript framework (many are part of this). Super important!
ggiraph (ggplot graphics interactive)
| library | R function | Functionality |
|---|---|---|
| polychart | rPlot | ggplot2-like |
| Morris | mPlot | Pretty time series |
| nvd3 | nPlot | Lines/areas/bars |
| xCharts | xPlot | Various graphs |
| Highcharts | hPlot | Interactive charts |
| Leaflet | new() | Interactive Maps |
| Rickshaw | new() | Real-time ts graphs |
| Dimple | dPlot | Business analytics |
plot/lattice-like function.
library(rCharts)
library(MESS)
data(happiness)
mydf <- happiness
mydf$size <- sqrt(mydf$population)/8
r1 <- rPlot(x = "tax",
y = "happy",
data = mydf,
type = "point",
color = "continent",
size = "size")
r1
Type: point, bar, line, …
Add layers: r1$layer(y= ..., copy_layer=TRUE, type="line")
plot/lattice-like function. Add layers and guides to plot ..
mydf2 <- data.frame(tax=c(1, 50),
happy=c(4.93, 7.09))
r1$layer(x = "tax",
y = "happy",
data = mydf2,
type = "line",
size=list(const=4))
r1$guides(y = list(title="New label",
min=0, max=12))
r1
layer \(\approx\) points/linesguides \(\approx\) axisaddParams \(\approx\) title, plot sizer3 <- rPlot(x = "tax", y = "happy",
data = mydf, type = "point",
color = "continent",
size = "size",
tooltip="#!function(item){
return ('Country: ' +item.country+
'
 Tax: ' +item.tax+
'% Happiness: ' +item.happy+
'<br> Pop: ' +item.population+
' mio.') }!#")
Passing javascript is non-trivial.
HighCharter
Mature charts, stocks (time series), maps. Good API.
library(highcharter)
hc <- highchart() %>%
hc_chart(type = "column") %>%
hc_title(text = "Denmark") %>%
hc_xAxis(categories = 2011:2016) %>%
hc_add_series(data = c(3806, 6184,
7557, 14792,
21315, 3016),
name = "Asylum seekers") %>%
hc_add_serie(name = "Syria",
data = c(429, 822,
1710, 7087,
8608, 777),
type = "spline")
hc
Data are added using one of the following functions
| Name | Function |
|---|---|
| hc_add_series | Add single series (named: data, name) |
| hc_add_series_list | Add list of named series |
| hc_add_series_df | Add data.frame. Name variables accordingly => plot type |
| hc_add_series_ts | Add and plot ts object. Extra argument: name |
| hc_add_series_scatter | Create and plot scatter from two vectors. Extra arguments (size, color, label) |
| hc_add_series_boxplot | Add and plot boxplots |
| hc_add_series_map | Add geojson map |
Chart types: line (default), column, boxplot, bubble, arearange, heatmap, funnel, pie, …
Also: the hchart function (a la plot)
| Function | Example |
|---|---|
| Title, subtitle | hc_title(text = "Temperature"), hc_subtitle(text = "Somewhere warm") |
| Axis | hc_xAxis(categories = month) |
| hc_yAxis(title = list(text = "Temperature"), labels = list(format = "{value} C")) | |
| Theme | hc_add_theme(hc_theme_sandsignika()) |
| Zoom | hc_chart(zoomType = "xy") |
| Export | hc_exporting(enabled = TRUE) |
| Tooltip | hc_tooltip(useHTML = TRUE, headerFormat="<table>", |
| pointFormat = "<tr><th>x-val</th><td>{point.x}</td></tr>" | |
| footerFormat = "</table>") | |
| Legend | hc_legend(enabled=FALSE) |
| Credits | hc_credits(enabled = TRUE, text = "Source: Wikipedia", href = "https://wikipedia.com", style = list(fontSize = "12px")) |
happiness$size <- sqrt(happiness$population)/8
hap <- happiness # Shorten name
happy2 <- highchart() %>%
hc_title(text = "Taxes and happiness") %>%
hc_subtitle(text = "Source: Wikipedia") %>%
hc_xAxis(title = list(text = "Taxation (%)")) %>%
hc_yAxis(title = list(text = "Happiness")) %>%
hc_chart(zoomType = "xy") %>% hc_exporting(enabled = TRUE) %>%
hc_add_serie_scatter(hap$tax, hap$happy,
hap$size, hap$continent, hap$country,
dataLabels = list( enabled = TRUE,
format = "{point.label}")) %>%
hc_tooltip(useHTML = TRUE,
headerFormat = "<table>",
pointFormat = paste("<tr><th colspan=\"1\"><b>{point.label}</b></th></tr>",
"<tr><th>Tax</th><td>{point.x} %</td></tr>",
"<tr><th>Score</th><td>{point.y}</td></tr>",
"<tr><th>Pop</th><td>{point.z} </td></tr>",
"<tr><th>Cont.</th><td>{point.valuecolor} hp</td></tr>",
"<tr><th>Religion</th><td>{point.extrainfo} hp</td></tr>"),
footerFormat = "</table>")
happy2
Take the airquality dataset. Plot series of temperature and wind speed for June using for example highcharter or polychart.
data(airquality)
aq <- subset(airquality, Month==6)
head(aq)
library(highcharter)
hc <- highchart() %>%
hc_chart(type = "column") %>%
hc_title(text = "Denmark") %>%
hc_xAxis(categories = aq$Day) %>%
hc_add_series(data = aq$Temp,
name = "Temperature") %>%
...
dygraphs
Same build-up as highcharter. Most of the information passed in dygraph and dyOptions.
xts extended time series
library(dygraphs)
library(MESS)
library(xts)
data(greenland)
rownames(greenland) <-
paste0(greenland$year, "-07-15")
greenland$year <- NULL
temp <- as.xts(greenland)
dygraph(temp,
main="Av. Summer temp") %>%
dyRangeSelector(dateWindow =
c("1960-01-01", "2011-01-01"))
Series can be added with dySeries.
| Function | Example |
|---|---|
| Title | dygraph(data, main = "My Title") |
| Axis | dyAxis("x", drawGrid = TRUE, label="My X axis") |
| Zoom/panning | dyRangeSelector() |
| Highlights | dyHighlight(highlightSeriesOpts = list(strokeWidth = 3)) |
| dyOptions/dySeries | Example |
|---|---|
| Step Plot | dyOptions(stepPlot = TRUE) |
| Colour | dyOptions(colors="blue") |
| Fill | dyOptions(fillGraph = TRUE, fillAlpha = 0.4) |
| L/V/U | A 3-vector name has special meaning (lower, value, upper). dySeries(c("L", "V", "U")) |
Also: dyShading, dyEvent, …
Danish Monthly births/deaths. Multiple series.
library(MESS)
library(dygraphs)
data(bdstat)
births <- ts(bdstat$births[1:(12*112)],
frequency=12,
start=c(1901, 1))
deaths <- ts(bdstat$dead[1:(12*112)],
frequency=12,
start=c(1901, 1))
DKdata <- cbind(births, deaths)
dygraph(DKdata,
main="Births/Deaths") %>%
dyAxis("x", drawGrid = FALSE) %>%
dySeries("births", drawPoints=TRUE,
color = "blue") %>%
dySeries("deaths", stepPlot = TRUE,
fillGraph = TRUE,
color = "red") %>%
dyHighlight(highlightSeriesOpts =
list(strokeWidth = 3))
Danish Monthly births/deaths. Multiple series. Prediciton
dkb <- HoltWinters(births)
p <- predict(dkb, n.ahead = 50*12,
prediction.interval=TRUE)
all <- cbind(births, p)
dygraph(all, main = "Births (DK)") %>%
dySeries("births", drawPoints = TRUE,
color = "blue",
label="asd") %>%
dySeries(c("p.lwr","p.fit","p.upr"),
color = "red")
Beautiful maps crated by adding layers on top of maps.
library(leaflet) m <- leaflet() %>% addTiles() %>% # Default OpenStreetMap map tiles addMarkers(lat=37.431106, lng=-122.164672, popup="useR 2016") m
Main functions
| Function | Example |
|---|---|
| Default map | addTiles() |
| Alternative maps | addProviderTiles("CartoDB.DarkMatter", options = providerTileOptions(opacity = 0.35)) Stackable! |
| Markers | addMarkers(~long, ~lat, popup = ~as.character(mag)) |
| Pop-ups | addPopups(lng=-122.164672, lat=37.431106, "<a href='http://www.user2016.org'> Hi </a>", options = popupOptions(closeButton = FALSE)) |
| Custom icons | makeIcon() |
library(leaflet)
library(MESS)
pal <- colorNumeric("RdYlBu",
domain = NULL)
data(earthquakes)
m <- leaflet(subset(earthquakes, mag>3)) %>%
addProviderTiles("CartoDB.DarkMatter") %>%
addCircleMarkers(
radius = ~ mag*3,
color = ~ pal(depth),
stroke = FALSE, fillOpacity = 0.4
)
m
Create your own icon and pop-up on this map.
library(leaflet) m <- leaflet() %>% addTiles() %>% # Default OpenStreetMap map tiles addMarkers(lng=-122.164672, lat=37.431106, popup="useR 2016") m
Add the R icon to the map: https://www.r-project.org/logo/Rlogo.png (Use icon instead of popup in addMarkers). Create simple icon:
greenLeafIcon <- makeIcon( iconUrl = "http://leafletjs.com/docs/images/leaf-green.png", iconWidth = 38, iconHeight = 95, iconAnchorX = 22, iconAnchorY = 94 )
Note: html/js output. Need javascript machinery to run (ie., html with js code embedded or online link).
library(htmlwidgets) saveWidget(widget, file, selfcontained = TRUE, background="white")
htmlwidget widgets behave nicely in R markdown.
as.iframe to appear.
Use ggplot2 (and grammar of graphics) to render interactive graphics.
plotly
Use legend to toggle traces, zoom, shift and click to pan. Super simple: p <- ggplot() ; ggplotly(p)
library(ggplot2)
library(plotly)
p <- ggplot(happiness,
aes(x=tax, y=happy, color=continent, size=population,
text = paste("country:", country))) +
geom_point( alpha = I(0.8)) +
scale_size_area(max_size = 30) +
geom_smooth(method="lm", se= F, size = 1,
aes(linetype = continent, group = continent))
ggplotly(p)
Just works (automatically embedded)
Embed the graph as an iframe
signup("username", "email", save=TRUE)
plotly_POST(p, "My Chart")
Extends ggplot2 with new geom functions.
geom_point_interactive, geom_polygon_interactive, geom_map_interactive, geom_path_interactive, geom_rect_interactive, geom_segment_interactive, geom_text_interactiveThree arguments let you add interactivity:
tooltip: mouse-over tooltips to be displayed when mouse is over elements.onclick: javascript function to be executed when elements are clicked.data_id: id to be associated with elements.library(ggiraph)
happiness$tooltip <- paste0("<table><th>Welcome to</th><tr><td>",
happiness$country,
"</td></tr></table>")
p <- ggplot(happiness,
aes(x=tax, y=happy, color=continent,
size=population, tooltip=tooltip)) +
geom_point_interactive(alpha=I(.8)) +
scale_size_area(max_size = 30)
ggiraph(code = {print(p)}, height = "350px")
library(ggiraph)
happiness$tooltip <- paste0("<table><th>Welcome to</th><tr><td>", happiness$country, "</td></tr></table>")
happiness$onclick <- sprintf(
"window.open(\"%s%s\")",
"http://en.wikipedia.org/wiki/",
as.character(happiness$country)
)
happiness$data_id <- happiness$country
p3 <- ggplot(happiness,
aes(x=tax, y=happy, color=continent,
size=population, tooltip=tooltip,
onclick=onclick, data_id=data_id)) +
geom_point_interactive(alpha=I(.8)) +
scale_size_area(max_size = 30)
ggiraph(code = print(p3),
hover_css = "fill-opacity:.3;cursor:pointer;", # data_id
width="600px", height = "300px"
)
Use ggplotly/ggiraph to create an interactive plot of development in average Danish life expectancy for males and females.
library(MESS) data(lifeexpect) head(lifeexpect)
## year male female myear ## 1 1840:1849 42.9 45.0 1844.5 ## 2 1850:1859 43.1 45.4 1854.5 ## 3 1860:1869 43.7 45.6 1864.5 ## 4 1870:1879 45.5 47.2 1874.5 ## 5 1880:1889 46.8 48.9 1884.5 ## 6 1890:1900 48.6 51.4 1895.0
Could start with
library(ggiraph)
p <- ggplot(lifeexpect,
aes(x=myear, y=male)) +
geom_path()
p
Use standard R. Rather simple and beautiful. Requires server, or running locally in R.
Two files
Directory | +-- ui.R +-- server.R
Or single file, app.R, with
server <- function(input, output) { ... }
ui <- fluidPage( ...)
shinyApp(ui = ui, server = server)
Run using
library(shiny)
runApp("/path/to/directory") # Local
runGitHub('ekstroem/ShinySampleMean') # From GitHub
library(shiny)
runGitHub('ekstroem/ShinySampleMean')
"Standard" design layout with sidebar for input and main window for output.
library(shiny)
shinyUI(pageWithSidebar(
titlePanel("My title"), # Application title
sidebarLayout( # Layout for this page
sidebarPanel( # Well a side bar panel
selectInput() # Input type
),
mainPanel(
plotOutput() # Types of output
) # ... and main panel
)
))
Communication through input and output lists.
library(shiny)
# Define server
shinyServer(function(input, output) {
output$something <- renderFunction(
v1 <- input$variable1 # Get input
...
)
})
checkboxInput - Check boxdateInput - Calendar to aid date selectiondateRangeInput - Pair of calendars for selecting a date rangefileInput - File upload control wizardnumericInput - Field to enter numbersradioButtons - Set of radio buttonsselectInput - Box with choices to select fromsliderInput - Slider bartextInput - Text areahtmlOutput - raw HTMLimageOutput - imageplotOutput - plottableOutput - tabletextOutput - textverbatimTextOutput - textInput functions are strings
renderImage - images (saved as a link to a source file)renderPlot - plotsrenderPrint - any printed outputrenderTable - data frame, matrix, other table like structuresrenderText - Raw textEach render* function takes a single argument: an R expression surrounded by braces, {}.
library(shiny)
ui <- fluidPage(
titlePanel("My title"),
sidebarLayout(
sidebarPanel(
selectInput("xvar", label = h3("Select x"),
choices = list("A"=1, "B"=2, "C"=3),
selected = 1)),
mainPanel(
textOutput("text"),
plotOutput("plot", height="600")
)))
server <- function(input, output) {
output$plot <- renderPlot({
mytext <- input$xvar
hist(rnorm(1000), col="lightred")
})
output$text <- renderText( { paste0("Hello ", mytext) } )
}
shinyApp(ui = ui, server = server)
runGitHub("ekstroem/useRapp")
Try to run the code from previous example. Add a slider to change the point size in the graph.
sliderInput (arguments: label, text, start value, min value, max value)