11 Interactive graphs tutorial

Chuyang Xiao

The following content is a brief and introductory tutorial about how to create interactive graphs with common packages of R.

11.1 Introduction

This rmd file incorporates a hand-by-hand tutorial about several useful tools to create interactive figures via multiple popular toolboxes. Though pretty attractive as well as persuasive during the data presentation, the creation of interactive diagrams is seldom mentioned during the lecture. Thus, I self-learnt a couple of useful tools and decided to make a detailed tutorial about how to create interactive diagrams.

Commonly, compared with the data selection, critical parameters determining the appearances and styles of the diagrams, such as the spline of the line or size of dots, are even more difficult to decide. Sometimes, it may be too laborious to alter the function parameters one-by-one and check the output. Hence, an interactive graph may be pretty helpful in this condition, which enables you to flexibly modify the appearances of the graphs. Moreover, during the data presentation, an interactive graph could also facilitate to emphasize specific characteristics as well as overall patterns of the graph.

In each of the following sections, you shall run the code chunk one-after-one. The description of the method is in front of the code chunk (please read it before running the code) and the analysis of the output would be after it. During the lecture, these contents have not been fully explained so far, and hence, I am pretty confident that, after finishing reading this tutorial, you could master a decent number of methods to create interactive graphs.

By the way, please read the rmd file rather than the html file to check out the graphs, since the dynamic graphs would become static if so.

11.2 Create Interactive Graphs via ggvis

The library ggvis is similar to ggplot2 from some extents, but it’s expressed a little differently, and adds new features to make your plots interactive.

The graphics produced by ggvis are mostly web graphics and work very differently from traditional R graphics. The presentation of graphs becomes various and fabulous, yet more computationally costly. For example, every interactive ggvis plot must be connected to a running R session (static plots do not need a running R session to be viewed). This is great for exploration, because you can do anything in your interactive plot you can do in R, but it’s not so great for publication. We will overcome these issues in time, but for now be aware that we have many existing tools to reimplement before you can do everything with ggvis that you can do with base graphics.

Firstly, we shall import the library of ggvis. (Since the installation of all packages are installed at the top of this file, if you do not mind, please uncomment the following contents to install them)

# if(!require(ggvis)) install.packages("ggvis")
# if(!require(dplyr)) install.packages("dplyr")

# library(ggvis)
# library(dplyr)

# Most of the following diagrams would be generated by the dataset "iris"
df <- iris

Similar to ggplot2, ggvis could also portray make basic plots

# Create an ordinary scatterplot
df %>%
  ggvis(~Sepal.Length,
        ~Sepal.Width, 
        fill=~Species) %>%
  layer_points()

Hence, it could be observed that ggvis could as well create scatterplot graphs, and the only difference would be the geom_points is changed into layer_points. On the other hand, there are also options to create similar basic graphs as ggplot. You could try these methods and their useful parameters as well:

  1. layer_bars(width = , stack = ): create a bar chart, the width stands for the width of each bar, and the stack represents that whether the bars are stacked
  2. layer_points(size = , fill = ): create a scatter plot, the size stands for the size of the dots, and
  3. layer_lines(): create a line chart
  4. layer_smooths(span = ): create a smooth conditional mean, the span stands for the extent of spanning of the line
  5. layer_histogram(width = ): create a histogram, and the width stands for the width of the bars
  6. layer_densities(kernel = ): create a density curve, and the kernel stands for the kind of distribution the curve tends to obey

In addition to the static graphs, the library ggvis is furthermore known for its abundant methods creating interactive graphs. For instance, via the input series method, you could modify the parameters above by a ux interface.

In the following code chunk, input_slider is employed, it would conduct sliders for the span of the conditional mean and the size of the dots. Please run the code below, try to slide the sliders and be aware of the changes in the graph. After you finish all modifications, please click on the esc key to exit the interactive interface.

df %>%
  ggvis(~Sepal.Length, ~Sepal.Width) %>%
  layer_smooths(span = input_slider(0.5, 1, value = 1, label = "Span")) %>%
  layer_points(size := input_slider(20, 100, value = 20, label = "Dot Sizes"))

As you just saw in the graph, there are two sliders at the bottom of the graph. By sliding them horizontally, you could determine the size of the dots and the span of smooths until an optimal state. Likewise, as you could see in the code, instead of a particular numeric value, the span and size are replaced by a new function input_slider. This input_slider method requires four parameters to set its range: the first two is the minimum and maximum of the range, the value is the default value of the slider, and the label defines the name of the slider. This interactive interface is pretty useful when determining continuous variables, such as sizes of dots in scatter plots and width of bars in bar charts and histograms.

By the way, the sliders inserted in the functions as parameter values could be reused. Just like the following code:

slider <- input_slider(20, 100, value = 20, label = "Dot Sizes")
df %>% ggvis(~Sepal.Length, ~Sepal.Width) %>%
  layer_points(size := slider) %>% 
  layer_points(fill := "red", opacity := 0.5, size := slider)

Just like the code above demonstrate, for parameters in same types and ranges, you could establish one slider object at first and then insert them into your function.

In addition to sliders, ggvis provides multiple methods to interact with the graph. Another common method would be input_select, which would provide a band including various options. Please run the code below, try to change the mode of kernel, and be aware of the changes in the graph. After you finish all modifications, please click on the esc key to exit the interactive interface.

df %>% ggvis(x = ~Sepal.Length) %>%
    layer_densities(
      adjust = input_slider(.1, 2, value = 1, step = .1, label = "Bandwidth adjustment"),
      kernel = input_select(
        c("Gaussian" = "gaussian",
          "Epanechnikov" = "epanechnikov",
          "Rectangular" = "rectangular",
          "Triangular" = "triangular",
          "Biweight" = "biweight",
          "Cosine" = "cosine",
          "Optcosine" = "optcosine"),
        label = "Kernel")
      )

In the interactive graph created above, it could be seen that there is a selection box at the bottom of the graph, and you could change the kernel via selecting different options in it. The code input_select would take a list as basic parameters, and the mapping between the displayed options and the internal parameters of the graph. For instance, the Gaussian appeared in the selection box would stand for the gaussian option for the kernel. Compared with slider object, this selection box is more appropriate for categorical parameters, such as the distribution, color, and shape.

In addition to sliders and selection box, ggvis also offers a number of other interactive controls, and each of them have particular applications:

  1. input_checkbox(): a check-box, this feature would be useful to determine boolean values
  2. input_checkboxgroup(): a group of check boxes, this feature would be useful to determine a number of boolean values
  3. input_numeric(): a spin box, best for numeric parameters
  4. input_radiobuttons(): pick one from a set options, best for categorical parameters
  5. input_select(): create a drop-down text box, best for categorical parameters
  6. input_text(): arbitrary text input, best for string inputs, such as x and y labels or titles.

To conclude, by replacing the static parameters in functions by these input series, you could flexibly modify any alterable parameters in the graph.

Moreover, ggvis also provides other sorts of interactive patterns useful in data presentations. When presenting a bar chart, you may need to emphasize a certain bar during the explanation. Hence, the parameter fill.hover would be helpful indeed. Please run the code below, swipe your mouse over each of the bars, and see the changes of the graph.

df %>% 
  ggvis(~Sepal.Length, 
        fill := "#fff8dc", 
        fill.hover := "#fcb5a2") %>%
  layer_histograms(width = 0.25)

Just like you just saw, a bar would change its color when your cursor is landing on it. It is the function of fill and fill.hover. The parameter fill.hover takes only one value, which is a specific color, and therefore the bar would turn into this color when touched by your cursor. It would be helpful when you are presenting the diagram to someone else.

Similarly, this method could be applied on other kind of graphs. Please run the code below, swipe your mouse over each line, and see the changes of the graph.

df %>% 
  ggvis(~Sepal.Length, 
        ~Sepal.Width,
        stroke = ~Species,
        stroke.hover := "red",
        strokeWidth := 2
        ) %>%
  layer_lines()

As you can see from the graph above, the line would turn red when your cursor lands on it. This function would be exceptionally useful when there are too many convoluted and overlapped lines and you could not specify one of them during the presentation.

To conclude, the package ggvis could cover the major functions of ggplot2, as well as create interactive graphs helpful during both the experiment and presentation.

11.3 Create Interactive Graphs via plotly

Similar to ggvis, plotly is also a powerful tool to create interactive graphs. Compared with conventional ggplot and ggvis, it could create more complicated as well as vivid graphs based on data from various sources.

At first, please run the code below to install the package. (Since the installation of all packages are installed at the top of this file, if you do not mind, please uncomment the following contents to install them)

# if(!require(plotly)) install.packages("plotly")

# library(plotly)

First and foremost, in plotly, the graph is created by the function plot_ly, and the style setting would be set by the function add_lines. Please run the code below and take a look at the graph created.

x <- seq(-2*pi, 2*pi, length.out = 1000)
df <- data.frame(x, y1 = cos(x))

fig <- plot_ly(df, x = ~x) %>% 
  add_lines(y = ~y1)

fig

If you move your cursor along the curve line, you could interact with the graph and then clearly see the x and y coordinates of the dots, which is truly helpful when you are estimating the maximum or minimum from the graph. Likewise, other kind of graphs could be created by the function plot_ly(data =, x =, type = XXX), and the XXX could be replace by any of the following methods:

‘bar’, ‘barpolar’, ‘box’, ‘candlestick’, ‘carpet’, ‘choropleth’, ‘choroplethmapbox’, ‘cone’, ‘contour’, ‘contourcarpet’, ‘densitymapbox’, ‘funnel’, ‘funnelarea’, ‘heatmap’, ‘heatmapgl’, ‘histogram’, ‘histogram2d’, ‘histogram2dcontour’, ‘icicle’, ‘image’, ‘indicator’, ‘isosurface’, ‘mesh3d’, ‘ohlc’, ‘parcats’, ‘parcoords’, ‘pie’, ‘pointcloud’, ‘sankey’, ‘scatter’, ‘scatter3d’, ‘scattercarpet’, ‘scattergeo’, ‘scattergl’, ‘scattermapbox’, ‘scatterpolar’, ‘scatterpolargl’, ‘scatterternary’, ‘splom’, ‘streamtube’, ‘sunburst’, ‘surface’, ‘table’, ‘treemap’, ‘violin’, ‘volume’, ‘waterfall’

However, the package plotly is far more than this. While ggvis could simply modify the appearances of the graphs, plotly could alter both the type and style of the graphs. In the following code, added a feature named updatememus, a panel one the figure that allows you to interact with it, is added to the figure. Please run the code below and try to push the two buttons and see the change in the graph.

fig = plot_ly(midwest, x = ~percollege, color = ~state, type = "box")

fig <- fig %>% layout(
  xaxis = list(domain = c(0.1, 1)),
  yaxis = list(title = "y"),
  updatemenus = list(
    list(
      type = "buttons",
      y = 0.8,
      # Establish a button to restyle the graph
      buttons = list(
        list(method = "restyle",
             args = list("type", "box"),
             label = "Box Graph"),
        
        list(method = "restyle",
             args = list("type", "violin"),
             label = "Violin Graph")
        ))
  ))

fig

According to the graph, you could easily see that the two buttons on the left could change the style of the graph into violin plot or box plot. Likewise, if you land your cursor on each box or violin, all statistic values including median, maximum, minimum and values of outliers would be shown, which is exceedingly convenient. Moreover, if you focus on the code, you could see that the two list in the button section corresponds with the two buttons on the left of the graph. The parameters in each list is defined as:

method = “restyle” : to modify the style of the graph, this parameter is always “restyle” args = list(“type”, “box”) : the first item type is the parameter in plot_ly that is desired to be changed, it could also be color label = “Box Graph” : the name appeared on the button

It is indeed easy to change the style of the graph by clicking on buttons, but please make sure that the input data is acceptable in all styles of graphs you choose.

Moreover, besides the style of the graphs, the color schema of the graphs could be modified as well in this pattern. Please run the code below and click on each button to see the changes they make in the graph.

fig <- plot_ly(z = ~as.matrix(mtcars), type = "heatmap", colorscale='Rainbow')

# chart option buttons
chart_types <- list(
  type = "buttons",
  direction = "right",
  xanchor = 'center',
  yanchor = "top",
  pad = list('r'= 0, 't'= 10, 'b' = 10),
  x = 0.5,
  y = 1.27,
  
  # type option buttons
  buttons = list(

    list(method = "restyle",
         args = list("type", "heatmap"),
         label = "Heatmap"),

    list(method = "restyle",
         args = list("type", "contour"),
         label = "Contour"),

    list(method = "restyle",
         args = list("type", "surface"),
         label = "Surface")
  ))

# color option buttons  
color_types <- list(
  type = "buttons",
  direction = "right",
  xanchor = 'center',
  yanchor = "top",
  pad = list('r'= 0, 't'= 10, 'b' = 10),
  x = 0.5,
  y = 1.17,
  buttons = list(

    list(method = "restyle",
         args = list("colorscale", "Rainbow"),
         label = "Rainbow"),

    list(method = "restyle",
         args = list("colorscale", "Jet"),
         label = "Jet"),

    list(method = "restyle",
         args = list("colorscale", "Earth"),
         label = "Earth"),

    list(method = "restyle",
         args = list("colorscale", "Electric"),
         label = "Electric")
  ))

annot <- list(list(text = "Chart<br>Type", x=0.2, y=1.25, xref='paper', yref='paper', showarrow=FALSE),
              list(text = "Color<br>Type", x=0.2, y=1.15, xref='paper', yref='paper', showarrow=FALSE))

# plot
fig <- fig %>% layout(
  xaxis = list(domain = c(0.1, 1)),
  yaxis = list(title = "y"),
  updatemenus = list(chart_types,color_types),
  annotations = annot)

fig

As you could observed in the graph above, when the data structure is suitable, it could be easily transformed into heatmap, contour lines, and surface graphs, as well as into various color schema. Regarding the code, the buttons are stored in two lists, the color types and chart types, and both of them are incorporated into the final graph and operate separately. Thus, if you would like to update a certain graph from various perspectives, please generate one kind of buttons within one list and zip them together as the updatemenus of the final graph. Besides, just like previous graphs, by moving your cursor on the graph, you could also see the 3-dimensional coordinate of each segment, or your could swipe your cursors up and down in the surface graph to zoom in or zoom out.

All in all, the previous shown content is just a tiny proportion of plotly, and this package still contains numerous powerful toolboxes to construct interactive graphs which you could further explore.

11.4 Create Interactive Graphs via networkD3

While packages such as ggplot2 and ggvis or plotly that mostly focus on presenting the values of the given data, the package networkD3 specializes in demonstrating the relationship of the data by tree diagrams or network diagrams. In addition, as these kinds of diagrams are relatively structured and simple in their form, the interactive pattern in this package may let you flexibly manipulate the diaragm to highlight certain parts.

At first, please run the code chunk below to install packages and import the libraries. (Since the installation of all packages are installed at the top of this file, if you do not mind, please uncomment the following contents to install them)

# if(!require(igraph)) install.packages("igraph")
# if(!require(networkD3)) install.packages("networkD3")

# library(igraph)
# library(networkD3)

Firstly, for a simply connected data, you could create a simple network by the function simpleNetwork. Please run the code chunk below and see the output graph. You could also drag the nodes on the diagrams to see what would happen.

# create a dataset:
data <- tibble(
  from=c("A", "A", "B", "D", "C", "D", "E", "B", "C", "D", "K", "A", "M"),
  to=c("B", "E", "F", "A", "C", "A", "B", "Z", "A", "C", "A", "B", "K")
)

# Plot
simpleNetwork(data,
              height="100px", 
              width="100px"
              )

As you could see in the diagram above, the connective relationship in the diagram is defined by two zipped lists, from and to. If there is a connection between the node a and b, please add a in the list from and add b in the list to, and then this edge would be presented in this graph. Moreover, the generated network graph is highly flexible, you could rearrange it flexibly into any expected form by simply dragging it by the cursor.

For hierarchical diagrams, the most appropriate function would be dendroNetwork, which would generate a tree diagram displaying the hierarchy of the items horizontally. Please run the code below and swipe your cursor along each child node on the right to see what happens.

df <- hclust(dist(mtcars), "ave")

dendroNetwork(df, fontSize = 10)

As you could see, the method above requires two sections. Firstly, it would cluster all child nodes (the model of the cars in the original data) in to hierarchical clusters by the method hclust. This method would take two parameters, the input dataframe, and the method to cluster them. In this case, the data is clustered based on their ave (average). Then, the hclust object generated would be displayed by the method dendroNetwork, which only accepts the hclust inputs, and conduct a tree diagram. In the diagram, the adjacency between child nodes represents their similarities in average. Furthermore, if you swipe your mouse over the nodes’ names, you could magnify their font immediately, and this function shall be pretty helpful during presentations.

In addition to simple networks, there are still other functions in this package that you may utilize: 1. sankeyNetwork: generate flow chart to illustrate the outflow and inflow 2. forceNetwork: have more control over the appearance of the forced directed network and to plot more complicated networks. 3. radialNetwork: have a radar-like appearances, where the source node locates at the center of the graph, and spreads out numerous child nodes. 4. diagonalNetwork: similar to the dendroNetwork, but links the nodes via smooth curves.

11.5 Conclusion

To summarize, there are still a number of fantastic tools to create interactive graphs, in addition to ggvis, plotly, and networkD3. However, if your could master most functions mentioned in this tutorial, it would be quite convenient to produce nice graphs in your projects.

11.6 Reference

Plotly R Graphing Library. (2021). R | Plotly. https://plotly.com/r/ Gandrud, Christopher. (2017). christophergandrud. http://christophergandrud.github.io/networkD3/