knitr::opts_chunk$set(echo = TRUE)

The current situation

Tkae the following data from mtcars:

d <- mtcars[, c('mpg', 'hp')]

Let's say we want to plot this with ggplot2. We would do

library(ggplot2)
ggplot(d, aes(x = mpg, y = hp)) + geom_point()

Which is awesome. Now let's say we wanted to specify finer breaks. We would add:

p <- ggplot(d, aes(x = mpg, y = hp)) + geom_point() + scale_x_continuous('mpg', breaks = seq(10, 35, by = 1))

Now let's say we want to rotate the labels 45 degrees and modify their appearance. We do

ggplot(d, aes(x = mpg, y = hp)) + geom_point() + scale_x_continuous('mpg', breaks = seq(10, 35, by = 1)) +
  theme(axis.text.x = element_text(face="bold", color="#993333", 
                           size=10, angle=45))

But let's now say we only wanted to make bold or rotate half of the labels, say the even ones. How can one do this? It doesn't seems easily possible.

In d3, one would do something like:

xAxis.selectAll("text") .attr("transform", "rotate(90)")

The nice thing about the d3 way of doing things is that one can modify only some specific label object, by doing e.g.

xAxis.selectAll("text") .attr("transform", function(d,i){ #code that modifies the label here depending on its index })

The not so nice way of doing things in d3 is that one needs to set up a lot of boilerplate code from the start: define the scales with their domain (the range of data they can take in from the user) and the range (the x - y coordinates ), define the axis with their associated scale and their position defined by a possible transformation, etc etc.

This becomes even more cumbersome when one wants to define interactions with the visual objects; a lot of code is needed to set these up even in simple cases.

The idea

The available viz libraries in R are all modelled after ggplot2 more or less (e.g. plotly, vegalite, etc); so they are fully declarative in spirit. This makes them easy to produce plots with but it limits how customizable they are in the end. D3 is fully customizable because it uses a system that allows to operate on visual elements individually using callback functions, but it is not declarative enough to be as easy to use as ggplot2. The idea: have a grammar that combines the two to have the full range of ease of use and full customizability.

Example one

Let's consider the example above. Ideally a good pseudo-syntax to do the same would be

d %>% vizr() %>% add_axis(x = mpg, y = hp) %>% 
  add_points() %>% set(x_axis$ticks = seq(10, 35, by = 1)) %>% 
  transform(x_axis$ticks, function(t){
    t$color <- '#ffff'
    t$face <- 'bold'
    t$rotation <- '90d'
  })

And to transform only the even ticks

d %>% vizr() %>% add_axis(x = mpg, y = hp) %>% 
  add_points() %>% set(x_axis$ticks = seq(10, 35, by = 1)) %>% 
  transform(x_axis$ticks, function(t){
    if (t$index %% 2 == 0){
    t$color <- '#ffff'
    t$face <- 'bold'
    t$rotation <- '90d'
    }
  })

every tick t in 'ticks' above should have a property 'index' that can be accessed from a function, and specifies the position of the tick in the tick list.

In general, a plot is specified as a tree of visual elements groups such as

root main -- legend x_axis -- y_axis -- canvas ticks -- labels -- ticks -- labels -- points

every visual element is an object with properties such as -- index (referring to the order in which it appears if needed) -- data (referring to the data which is stored/bound to the element) -- visual properties (referring to the visual properties of the object: colour, size, etc)

transformations on an object apply to all the objects under it in the tree, e.g. translations of an axis.

for the interactions, we should have commands like on_hover or on_click which accept tree elements and callback functions.

The idea should be: functional programming on visual and interactive elements!

In terms of translation to D3, ideally the final visualization would be a d3 closure composed of other closure functions in a modular way. This could be generated using htmlwidgets like:

R syntax -> declarative specification as an object -> D3 closure



riccardopinosio/funviz documentation built on May 4, 2019, 7:38 a.m.