+ - 0:00:00
Notes for current slide
Notes for next slide

Why JavaScript?

Carson Sievert, PhD
Software Engineer, RStudio

Slides: http://bit.ly/jsm_19

@cpsievert
https://cpsievert.me
cpsievert1@gmail.com

1 / 26
Mo us t ach ivation
2 / 26

Why not

Why JavaScript?

Carson Sievert, PhD
Software Engineer, RStudio

Slides: http://bit.ly/jsm_19

@cpsievert
https://cpsievert.me
cpsievert1@gmail.com

3 / 26

When to

Why JavaScript?

Carson Sievert, PhD
Software Engineer, RStudio

Slides: http://bit.ly/jsm_19

@cpsievert
https://cpsievert.me
cpsievert1@gmail.com

4 / 26

"Of course someone has to write for loops.
It doesnโ€™t have to be you."

  • Jenny Bryan (Software Engineer, RStudio)
5 / 26

JavaScript

"Of course someone has to write for loops. It doesnโ€™t have to be you."

  • Me, for similar reasons
6 / 26

JavaScript

Why avoid for loops?

"It is all too easy for statistical thinking to be swamped by programming tasks." (Brian D. Ripley)

7 / 26

What does this R code do?

out1 <- vector("double", ncol(mtcars))
for (i in seq_along(mtcars)) {
out1[[i]] <- mean(mtcars[[i]], na.rm = TRUE)
}
out2 <- vector("double", ncol(mtcars))
for (i in seq_along(mtcars)) {
out2[[i]] <- median(mtcars[[i]], na.rm = TRUE)
}

Example from Hadley Wickham's Building Tidy Tools workshop.

8 / 26

For loops emphasize the objects

out1 <- vector("double", ncol(mtcars))
for (i in seq_along(mtcars)) {
out1[[i]] <- mean(mtcars[[i]], na.rm = TRUE)
}
out2 <- vector("double", ncol(mtcars))
for (i in seq_along(mtcars)) {
out2[[i]] <- median(mtcars[[i]], na.rm = TRUE)
}

Example from Hadley Wickham's Building Tidy Tools workshop.

9 / 26

Not the actions

out1 <- vector("double", ncol(mtcars))
for (i in seq_along(mtcars)) {
out1[[i]] <- mean(mtcars[[i]], na.rm = TRUE)
}
out2 <- vector("double", ncol(mtcars))
for (i in seq_along(mtcars)) {
out2[[i]] <- median(mtcars[[i]], na.rm = TRUE)
}

Example from Hadley Wickham's Building Tidy Tools workshop.

10 / 26

Functional programming weights equally

library(purrr)
means <- map_dbl(mtcars, mean)
medians <- map_dbl(mtcars, median)

Example from Hadley Wickham's Building Tidy Tools workshop.

11 / 26

Functional programming weights equally

library(purrr)
means <- map_dbl(mtcars, mean)
medians <- map_dbl(mtcars, median)

For more, see "The Joy of Functional Programming (for Data Science)" by Hadley Wickham

Example from Hadley Wickham's Building Tidy Tools workshop.

12 / 26
JavaScript/D3

For loop emphasizes objects




<<<<<<< HEAD

The low-level graphics API (e.g. SVG, Canvas, etc) is often far removed from the domain problem

=======

The low-level graphics API (e.g. SVG, Canvas, etc) is often far removed from your overall intention

33954554f8941382265863747cf0e68e283cb226

13 / 26

'High-level' JS libraries

<html>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<body>
<div id="graph"></div>
</body>
</html>
var bar = {
x: [1, 2, 3],
y: ["a", "b", "c"],
type: "bar"
}
Plotly.plot("graph", {data: [bar]})
14 / 26

'High-level' JS libraries

<<<<<<< HEAD

- ๐Ÿ‘ Compared to D3, more weight on the intention

  • ๐Ÿ‘ Compared to D3, more weight on the overall intention

    33954554f8941382265863747cf0e68e283cb226

  • ๐Ÿ‘Ž HTML boilerplate
  • ๐Ÿ‘Ž Web tech is not designed for data exploration, but R is!


<html>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<body>
<div id="graph"></div>
</body>
</html>
var bar = {
x: [1, 2, 3],
y: ["a", "b", "c"],
type: "bar"
}
Plotly.plot("graph", {data: [bar]})
15 / 26
16 / 26

htmlwidgets: a bridge between R and JS libraries

17 / 26

htmlwidgets: computing+graphics synergy

library(plotly)
albersusa::usa_sf("laea") %>%
cartogram::cartogram_cont("pop_2014") %>%
plot_ly(us_cont) %>%
add_sf(color = ~pop_2014, split = ~name, span = I(1), text = ~paste(name, scales::number_si(pop_2014))) %>%
colorbar(title = "Population \n 2014")
18 / 26

htmlwidgets: within view interaction for 'free'

library(plotly)
plot_ly(diamonds, x = ~cut, color = ~clarity, colors = "Accent")

19 / 26

What about across view interaction?

20 / 26

shiny: manage communication across views

Most htmlwidgets allow you to access user events in shiny

library(shiny)
ui <- fluidPage(
plotlyOutput("p"),
verbatimTextOutput("click")
)
server <- function(input, output) {
output$p <- renderPlotly({
plot_ly(mtcars, x = ~wt, y = ~mpg)
})
output$click <- renderPrint({
event_data("plotly_click")
})
}
shinyApp(ui, server)

21 / 26

shiny itself isn't slow, your R code is!

Do you need to redraw the entire graph? Probably not!

22 / 26

What about "non-standard interaction"?

23 / 26

Time to JavaScript!

plot_ly(mtcars, x = ~wt, y = ~mpg) %>%
add_markers(
customdata = paste0(
"http://google.com/#q=", rownames(mtcars)
)
) %>%
htmlwidgets::onRender("
function(el) {
el.on('plotly_click', function(d) {
var url = d.points[0].customdata;
window.open(url);
});
}
")

Learn more about registering custom JavaScript events with plotly -- https://plotly-r.com/javascript.html

24 / 26

In summary

  • Programming in JavaScript, like for loops, can distract from the main task/action.

    • Over-emphasis on objects that are far removed from your overall intention
  • R bindings to JS libs (i.e., htmlwidgets, shiny, etc), best of both worlds!

    • If you hit a dead-end with these tools, then it's time to learn JavaScript!
25 / 26
Mo us t ach ivation
2 / 26
Paused

Help

Keyboard shortcuts

โ†‘, โ†, Pg Up, k Go to previous slide
โ†“, โ†’, Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow