-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy path3-20-htmlwidgets-intro.Rmd
154 lines (107 loc) Β· 6.74 KB
/
3-20-htmlwidgets-intro.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# (PART) Data Visualisation {-}
# Introduction to Widgets {#widgets-intro-intro}
```{r include=FALSE}
source("utils.R")
```
This part of the book explores the integration of JavaScript with R using the htmlwidgets\index{htmlwidgets} package, which focuses on libraries that produce a visual output. It is often used for data visualisation but is not limited to it.
As in future parts of this book, we mainly learn through examples, building multiple widgets of increasing complexity as we progress through the chapters. Before writing the first widget, we explore existing R packages that allow creating interactive data visualisations as this gives a first glimpse at what we ultimately build in this part of the book. Then we explore JavaScript libraries that make great candidates for htmlwidgets and attempt to understand how they work to grasp what is expected from the developer in order to integrate them with R. Finally, we build upon the previous chapter to improve how htmlwidgets work with Shiny\index{Shiny}.
The htmlwidgets\index{htmlwidgets} package originates from the rCharts [@R-rCharts] package created in 2012 by Ramnath Vaidyanathan. It brought together a plethora of data visualisation\index{visualisation} JavaScript libraries, datamaps, highcharts, morris.js, and many more. Though no longer maintained rCharts ultimately paved the way towards a framework for interactive visualisations in R: two years later, in 2014, Ramnath and other prominent R users start working on htmlwidgets.
The objective of this chapter is to explore existing widgets available on CRAN\index{CRAN}, discover how they work, whilst focusing on their prominent features as we learn how to implement those in our very own widget in the coming chapters.
## Plotly package {#widgets-plotly}
The plotly [@R-plotly] R package is probably one of the first and the most popular widget built thus far; it has been downloaded from CRAN\index{CRAN} 4.9 million times at the time of writing this.
Plotly.js is a substantial library that provides over 40 chart types, including 3D charts, statistical graphs, and maps, all of which are available from the R interface. There is so much depth to plotly that there is an entire [book](https://plotly-r.com/) on the topic: *Interactive web-based data visualization with R, plotly, and shiny.*
The very short snippet of code below creates Figure \@ref(fig:plotly-scatter-diagram), an interactive scatter plot.
```{r, eval=FALSE}
library(plotly)
plot_ly(cars, x = ~speed, y = ~dist) %>%
add_markers()
```
```{r plotly-scatter-diagram, message = FALSE, warning = FALSE, fig.pos = "H", warning=FALSE, error=FALSE, echo=FALSE, fig.cap='plotly scatter plot'}
library(plotly)
p <- plot_ly(cars, x = ~speed, y = ~dist) %>%
add_markers()
include_widget(p, "03-plotly-scatter.png")
```
Plotly also has the ability to translate static ggplot2 [@R-ggplot2] charts to interactive plotly charts with the `ggplotly` function, as demonstrated in Figure \@ref(fig:plotly-ggplotly-diagram).
```{r, eval=FALSE}
p <- ggplot(diamonds, aes(x = log(carat), y = log(price))) +
geom_hex(bins = 100)
ggplotly(p)
```
```{r plotly-ggplotly-diagram, fig.pos = "H", echo=FALSE, fig.cap='Interactive ggplot2 with plotly'}
p <- ggplot(diamonds, aes(x = log(carat), y = log(price))) +
geom_hex(bins = 100)
include_widget(ggplotly(p), "03-ggplotly.png")
```
All plotly charts are initialised with the `plot_ly` function and work nicely with the magrittr [@R-magrittr] pipe\index{pipe} `%>%`. This implies that (almost) every function expects a plotly object (the output of `plot_ly`) and returns a modified version of that object. The pipe\index{pipe} makes code easier to read and more concise.
```{r}
p <- plot_ly(cars, x = ~speed, y = ~dist)
p <- add_markers(p)
```
Plotly implements geoms in a similar fashion as ggplot2, functions that start in `add_` add a layer to the plot (e.g.: `add_lines`, `add_bars`), making it easy to combine series into a single chart, as in Figure \@ref(fig:plotly-layers-diagram).
```{r, eval=FALSE}
plot_ly(mtcars, x = ~disp) %>%
add_markers(y = ~mpg, text = rownames(mtcars)) %>%
add_lines(y = ~fitted(loess(mpg ~ disp)))
```
```{r plotly-layers-diagram, fig.pos = "H", echo=FALSE, fig.cap='Multiple layers with plotly'}
p <- plot_ly(mtcars, x = ~disp) %>%
add_markers(y = ~mpg, text = rownames(mtcars)) %>%
add_lines(y = ~fitted(loess(mpg ~ disp)))
include_widget(p, "03-plotly-multiple.png")
```
## DT package {#widgets-intro-dt}
The DT package [@R-DT] is a wrapper for the [DataTables](https://datatables.net/) jQuery plug-in, which allows creating interactive tables from R `data.frame` objects, it's as simple as a single line of code (see Figure \@ref(fig:plotly-dt-diagram)).
```{r, eval=FALSE}
DT::datatable(cars)
```
```{r plotly-dt-diagram, fig.pos = "H", echo=FALSE, fig.cap='Interactive table with DT'}
d <- DT::datatable(cars)
include_widget(d, "03-DT.png")
```
DT has grown very popular amongst Shiny developers as it allows capturing server-side many of the users' interactions with the table, such as the selected row, as demonstrated in Figure \@ref(fig:dt-example).
```r
library(DT)
library(shiny)
ui <- fluidPage(
fluidRow(
column(8, DTOutput("myTable")),
column(
4,
h4("Indices of selected rows"),
verbatimTextOutput("selected")
)
)
)
server <- function(input, output) {
output$myTable <- renderDT({
datatable(mtcars)
})
output$selected <- renderPrint({
input$myTable_rows_selected
})
}
shinyApp(ui, server)
```
```{r dt-example, fig.pos="H", echo=FALSE, fig.cap='DT package example'}
knitr::include_graphics("images/DT-example.png")
```
## Crosstalk {#widgets-intro-crosstalk}
DT and plotly both fully support the crosstalk package [@R-crosstalk], a package to enable two widgets to communicate. In the Figure \@ref(fig:dt-example-crosstalk), we use crosstalk to create a "shared dataset" that can be used to create 1) a table with DT, and 2) a scatter plot with plotly. Rows selected in the table are highlighted in the plot and vice versa.
The `bscols` function is just a convenience function that makes it easy to put the visualisation and table side-by-side.
```r
library(DT)
library(plotly)
library(crosstalk)
sd <- SharedData$new(iris[, c("Sepal.Length", "Sepal.Width")])
bscols(
device = "lg",
datatable(sd, width = "100%"),
plot_ly(sd, x = ~Sepal.Length, y = ~Sepal.Width)
)
```
```{r dt-example-crosstalk, fig.pos="H", echo=FALSE, fig.cap='DT and plotly with crosstalk'}
knitr::include_graphics("images/dt-crosstalk-intro.png")
```
## Wrap-up {#widgets-intro-conclude}
These are only two examples of widgets and how they can work together. But we hope this makes a compelling case for building such software as we next learn how to build them, integrate them with crosstalk, Shiny\index{Shiny}, and much more.