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:
-
layer_bars(width = , stack = )
: create a bar chart, thewidth
stands for the width of each bar, and thestack
represents that whether the bars are stacked -
layer_points(size = , fill = )
: create a scatter plot, thesize
stands for the size of the dots, and -
layer_lines()
: create a line chart -
layer_smooths(span = )
: create a smooth conditional mean, thespan
stands for the extent of spanning of the line -
layer_histogram(width = )
: create a histogram, and thewidth
stands for the width of the bars -
layer_densities(kernel = )
: create a density curve, and thekernel
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:
-
input_checkbox()
: a check-box, this feature would be useful to determine boolean values -
input_checkboxgroup()
: a group of check boxes, this feature would be useful to determine a number of boolean values -
input_numeric()
: a spin box, best for numeric parameters -
input_radiobuttons()
: pick one from a set options, best for categorical parameters -
input_select()
: create a drop-down text box, best for categorical parameters -
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/