-
Notifications
You must be signed in to change notification settings - Fork 48
/
bookdown.tex
10884 lines (8326 loc) Β· 612 KB
/
bookdown.tex
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\PassOptionsToPackage{unicode=true}{hyperref} % options for packages loaded elsewhere
\PassOptionsToPackage{hyphens}{url}
\PassOptionsToPackage{dvipsnames,svgnames*,x11names*}{xcolor}
%
\documentclass[10pt,]{krantz}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{ifxetex,ifluatex}
\usepackage{fixltx2e} % provides \textsubscript
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp} % provides euro and other symbols
\else % if luatex or xelatex
\usepackage{unicode-math}
\defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase}
\setmonofont[Mapping=tex-ansi,Scale=0.7]{Source Code Pro}
\fi
% use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
% use microtype if available
\IfFileExists{microtype.sty}{%
\usepackage[]{microtype}
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\IfFileExists{parskip.sty}{%
\usepackage{parskip}
}{% else
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
}
\usepackage{xcolor}
\usepackage{hyperref}
\hypersetup{
pdftitle={JavaScript for R},
pdfauthor={John Coene},
colorlinks=true,
linkcolor=Maroon,
filecolor=Maroon,
citecolor=Blue,
urlcolor=Blue,
breaklinks=true}
\urlstyle{same} % don't use monospace font for urls
\usepackage{color}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
% Add ',fontsize=\small' for more characters per line
\usepackage{framed}
\definecolor{shadecolor}{RGB}{248,248,248}
\newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}}
\newcommand{\AlertTok}[1]{\textcolor[rgb]{0.33,0.33,0.33}{#1}}
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textbf{\textit{#1}}}}
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.61,0.61,0.61}{#1}}
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.06,0.06,0.06}{#1}}
\newcommand{\BuiltInTok}[1]{#1}
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.5,0.5,0.5}{#1}}
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}}
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textbf{\textit{#1}}}}
\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0,0,0}{#1}}
\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.27,0.27,0.27}{\textbf{#1}}}
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.27,0.27,0.27}{#1}}
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.06,0.06,0.06}{#1}}
\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textbf{\textit{#1}}}}
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.14,0.14,0.14}{\textbf{#1}}}
\newcommand{\ExtensionTok}[1]{#1}
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.06,0.06,0.06}{#1}}
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0,0,0}{#1}}
\newcommand{\ImportTok}[1]{#1}
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textbf{\textit{#1}}}}
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.27,0.27,0.27}{\textbf{#1}}}
\newcommand{\NormalTok}[1]{#1}
\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.43,0.43,0.43}{\textbf{#1}}}
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}}
\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}}
\newcommand{\RegionMarkerTok}[1]{#1}
\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0,0,0}{#1}}
\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.5,0.5,0.5}{#1}}
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.5,0.5,0.5}{#1}}
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0,0,0}{#1}}
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.5,0.5,0.5}{#1}}
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textbf{\textit{#1}}}}
\usepackage{longtable,booktabs}
% Fix footnotes in tables (requires footnote package)
\IfFileExists{footnote.sty}{\usepackage{footnote}\makesavenoteenv{longtable}}{}
\usepackage{graphicx,grffile}
\makeatletter
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
\makeatother
% Scale images if necessary, so that they will not overflow the page
% margins by default, and it is still possible to overwrite the defaults
% using explicit options in \includegraphics[width, height, ...]{}
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setcounter{secnumdepth}{5}
% Redefines (sub)paragraphs to behave more like sections
\ifx\paragraph\undefined\else
\let\oldparagraph\paragraph
\renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}}
\fi
\ifx\subparagraph\undefined\else
\let\oldsubparagraph\subparagraph
\renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}}
\fi
% set default figure placement to htbp
\makeatletter
\def\fps@figure{htbp}
\makeatother
\usepackage{booktabs}
\usepackage{longtable}
\usepackage[bf,singlelinecheck=off]{caption}
\usepackage{framed,color}
\definecolor{shadecolor}{RGB}{248,248,248}
\renewcommand{\textfraction}{0.05}
\renewcommand{\topfraction}{0.8}
\renewcommand{\bottomfraction}{0.8}
\renewcommand{\floatpagefraction}{0.75}
\renewenvironment{quote}{\begin{VF}}{\end{VF}}
\let\oldhref\href
\renewcommand{\href}[2]{#2\footnote{\url{#1}}}
\makeatletter
\newenvironment{kframe}{%
\medskip{}
\setlength{\fboxsep}{.8em}
\def\at@end@of@kframe{}%
\ifinner\ifhmode%
\def\at@end@of@kframe{\end{minipage}}%
\begin{minipage}{\columnwidth}%
\fi\fi%
\def\FrameCommand##1{\hskip\@totalleftmargin \hskip-\fboxsep
\colorbox{shadecolor}{##1}\hskip-\fboxsep
% There is no \\@totalrightmargin, so:
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}%
\MakeFramed {\advance\hsize-\width
\@totalleftmargin\z@ \linewidth\hsize
\@setminipage}}%
{\par\unskip\endMakeFramed%
\at@end@of@kframe}
\makeatother
\renewenvironment{Shaded}{\begin{kframe}}{\end{kframe}}
\newenvironment{rmdblock}[1]
{
\begin{itemize}
\renewcommand{\labelitemi}{
\raisebox{-.7\height}[0pt][0pt]{
{\setkeys{Gin}{width=3em,keepaspectratio}\includegraphics{images/#1}}
}
}
\setlength{\fboxsep}{1em}
\begin{kframe}
\item
}
{
\end{kframe}
\end{itemize}
}
\newenvironment{rmdnote}
{\begin{rmdblock}{note}}
{\end{rmdblock}}
\newenvironment{rmdcaution}
{\begin{rmdblock}{caution}}
{\end{rmdblock}}
\newenvironment{rmdimportant}
{\begin{rmdblock}{important}}
{\end{rmdblock}}
\newenvironment{rmdtip}
{\begin{rmdblock}{tip}}
{\end{rmdblock}}
\newenvironment{rmdwarning}
{\begin{rmdblock}{warning}}
{\end{rmdblock}}
\usepackage{makeidx}
\makeindex
\urlstyle{tt}
\usepackage{amsthm}
\makeatletter
\def\thm@space@setup{%
\thm@preskip=8pt plus 2pt minus 4pt
\thm@postskip=\thm@preskip
}
\makeatother
\usepackage{float}
\frontmatter
\usepackage[]{natbib}
\bibliographystyle{apalike}
\title{JavaScript for R}
\author{John Coene}
\date{2021-04-22}
\begin{document}
\maketitle
% you may need to leave a few empty pages before the dedication page
%\cleardoublepage\newpage\thispagestyle{empty}\null
%\cleardoublepage\newpage\thispagestyle{empty}\null
%\cleardoublepage\newpage
\thispagestyle{empty}
\begin{center}
%\includegraphics{images/dedication.pdf}
\end{center}
\setlength{\abovedisplayskip}{-5pt}
\setlength{\abovedisplayshortskip}{-5pt}
{
\hypersetup{linkcolor=}
\setcounter{tocdepth}{2}
\tableofcontents
}
\listoffigures
\hypertarget{preface}{%
\chapter*{Preface}\label{preface}}
The R programming language has seen the integration of many languages; C, C++, Python, to name a few, can be seamlessly embedded into R so one can conveniently call code written in other languages from the R console. Little known to many, R works just as well with JavaScript---this book delves into the various ways both languages can work together.
The ultimate aim of this work is to demonstrate to readers the many great benefits can reap by inviting JavaScript into their data science workflow. In that respect, the book is not teaching one JavaScript but instead demonstrates how little JavaScript can significantly support and enhance R code. Therefore, the focus is on integrating external JavaScript libraries and only limited knowledge of JavaScript is required in order to learn from the book. Moreover, the book focuses on generalisable learnings so the reader can transfer takeaways from the book to solve real-world problems.
Throughout the book, several Shiny applications and R packages are put together as examples. All of these, along with the code for the entire book, can be found on the GitHub repository: \href{https://github.com/JohnCoene/javascript-for-r}{github.com/JohnCoene/javascript-for-r}.
\hypertarget{premise}{%
\section*{Premise}\label{premise}}
The R programming language has been propelled into web browsers with the introduction of packages such as \href{https://shiny.rstudio.com/}{Shiny} \citep{R-shiny} and \href{https://rmarkdown.rstudio.com/}{rmarkdown} \citep{R-rmarkdown} which have greatly improved how R users can communicate complex insights by building interactive web applications and interactive documents. Yet most R developers are not familiar with one of web browsers' core technology: JavaScript. This book aims to remedy that by revealing how much JavaScript can greatly enhance various stages of data science pipelines from the analysis to the communication of results.
Notably, the focus of the book truly is the integration of JavaScript with R, where both languages either actively interact with one another, or where JavaScript enables doing things otherwise not accessible to R users. It is not merely about including JavaScript code that works alongside R.
\hypertarget{book-structure}{%
\section*{Book Structure}\label{book-structure}}
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
The book opens with an introduction to illustrate its premise better it provides rationales for using JavaScript in conjunction with R, which it supports with existing R packages that use JavaScript and are available on CRAN. Then it briefly describes concepts essential to understanding the rest of the book to ensure the reader can follow along. Finally, this part closes by listing the various methods with which one might make JavaScript work with R.
\item
We explore existing integrations of JavaScript and R namely by exploring packages to grasp how these tend to work and the interface to JavaScript they provide.
\item
A sizeable part of the book concerns data visualisation it plunges into creating interactive outputs with the htmlwidgets package. This opens with a brief overview of how it works and libraries that make great candidates to integrate with the htmlwidgets package. Then a first, admittedly unimpressive, widget is built to look under the hood and observe the inner workings of such outputs to grasp a better understanding of how htmlwidgets work. Next, we tackle a more substantial library that allows drawing arcs between countries on a 3D globe, which we cover in great depth. The last two chapters go into more advanced topics, such as security and resizing.
\item
The fourth part of the book details how JavaScript can work with Shiny. Once the basics are out of the way, the second chapter builds the first utility to display notifications programmatically. Then we create a Shiny application that runs an image classification algorithm in the browser. This is then followed by the creation of custom Shiny inputs and outputs. Finally, Shiny and htmlwidgets are (literally) connected by including additional functionalities in interactive visualisations when used with the Shiny framework.
\item
Then the book delves into using JavaScript for computations, namely via the V8 engine and Node.js. After a short introduction, chapters will walk the reader through various examples: a fuzzy search, a time format converter, and some basic natural language operations.
\item
Finally, we look at how one can use some of the more modern JavaScript technologies such as Vue\index{Vue}, React, and webpack with R---these can make the use of JavaScript more agile and robust.
\item
Next the book closes with examples of all the integrations explored previously. This involves recreating (a part of) the plotly package, building an image classifier, adding progress bars to a Shiny application, building an app with HTTP cookies, and running basic machine learning operations in JavaScript.
\item
Finally, the book concludes with some noteworthy remarks on where to go next.
\end{enumerate}
\hypertarget{acknowledgement}{%
\section*{Acknowledgement}\label{acknowledgement}}
Many people in the R community have inspired me and provided the knowledge to write this book, amongst them ultimately are \href{https://github.com/ramnathv/}{Ramnath Vaidyanathan,} for his amazing work on the htmlwidgets \citep{R-htmlwidgets} package \href{https://github.com/timelyportfolio}{Kent Russell,} from whom I have learned a lot via his work on making Vue and React accessible in R and \href{https://github.com/cpsievert}{Carson Sievert,} for pioneering probably the most popular integration of R and JavaScript with the plotly \citep{R-plotly} package.
Early reviewers also shared precious feedback that helped make the book dramatically better, thanks to \href{@mayacelium}{Maya Gans,} \href{@felipe_mattioni}{Felipe Mattioni Maturana,} and \href{@Wei_Su}{Wei Su} for thoroughly going through every line of the book.
Thanks to \href{https://www.davisuko.com/}{Cody Davis} for the cover image of the book.
\mainmatter
\hypertarget{part-basics-and-roadmap}{%
\part{Basics and Roadmap}\label{part-basics-and-roadmap}}
\hypertarget{intro-overview}{%
\chapter{Overview}\label{intro-overview}}
This book starts with a rationale for integrating JavaScript with R and supports it with examples, namely packages that use JavaScript and are available on CRAN\index{CRAN}. Then, we list the various ways in which one might go about making both languages work together. In the next chapter, we go over prerequisites and a review of concepts fundamental to fully understand the more advanced topics residing in the forthcoming chapters.
\hypertarget{intro-overview-rationale}{%
\section{Rationale}\label{intro-overview-rationale}}
Why blend two languages seemingly so far removed from each other? Well, precisely because they are fundamentally different languages that each have their strengths and weaknesses; combining the two allows making the most of their consolidated advantages and circumvents their respective limitations to produce software altogether better for it.
Nevertheless, a fair reason to use JavaScript might be that the thing one wants to achieve in R has already been realised in JavaScript. Why reinvent the wheel when the solution already exists and that it can be made accessible from R? The R package \href{https://github.com/ateucher/rmapshaper}{rmapshaper} \citep{R-rmapshaper} by Andy Teucher that integrates \href{https://github.com/mbloch/mapshaper/}{mapshaper,} a library to edit geo-spatial-related files such as GeoJSON, or TopoJSON. JavaScript is by no means required to make those computations; they could be rewritten solely in R, but that would be vastly more laborious than wrapping the JavaScript API in R as done by the package rmapshaper.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{library}\NormalTok{(rmapshaper)}
\CommentTok{# get data}
\KeywordTok{data}\NormalTok{(states, }\DataTypeTok{package =} \StringTok{"geojsonio"}\NormalTok{)}
\NormalTok{states_json <-}\StringTok{ }\NormalTok{geojsonio}\OperatorTok{::}\KeywordTok{geojson_json}\NormalTok{(}
\NormalTok{ states, }
\DataTypeTok{geometry =} \StringTok{"polygon"}\NormalTok{, }
\DataTypeTok{group =} \StringTok{"group"}
\NormalTok{)}
\CommentTok{#> Registered S3 method overwritten by 'geojsonsf':}
\CommentTok{#> method from }
\CommentTok{#> print.geojson geojson}
\CommentTok{#> Assuming 'long' and 'lat' are longitude and latitude, respectively}
\NormalTok{states_sp <-}\StringTok{ }\NormalTok{geojsonio}\OperatorTok{::}\KeywordTok{geojson_sp}\NormalTok{(states_json)}
\CommentTok{# print shape file size}
\KeywordTok{print}\NormalTok{(}\KeywordTok{object.size}\NormalTok{(states_sp), }\DataTypeTok{units =} \StringTok{"Mb"}\NormalTok{)}
\CommentTok{#> 0.4 Mb}
\CommentTok{# simplify with rmapshaper}
\NormalTok{states_sm <-}\StringTok{ }\NormalTok{rmapshaper}\OperatorTok{::}\KeywordTok{ms_simplify}\NormalTok{(states_sp, }\DataTypeTok{keep =} \FloatTok{0.05}\NormalTok{)}
\CommentTok{# print reduced size}
\KeywordTok{print}\NormalTok{(}\KeywordTok{object.size}\NormalTok{(states_sm), }\DataTypeTok{units =} \StringTok{"Mb"}\NormalTok{)}
\CommentTok{#> 0.2 Mb}
\end{Highlighting}
\end{Shaded}
Another great reason is that JavaScript can do things that R cannot, e.g., run in the browser. Therefore, one cannot natively create interactive visualisations with R. \href{https://plotly-r.com/}{Plotly} \citep{R-plotly} by Carson Sievert packages the \href{https://plot.ly/}{plotly JavaScript library} to let one create interactive visualisations solely from R code as shown in Figure \ref{fig:plotly-basic-example}.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{library}\NormalTok{(plotly)}
\KeywordTok{plot_ly}\NormalTok{(diamonds, }\DataTypeTok{x =} \OperatorTok{~}\NormalTok{cut, }\DataTypeTok{color =} \OperatorTok{~}\NormalTok{clarity, }\DataTypeTok{width =} \StringTok{"100%"}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/01-plotly}
}
\caption{Basic htmlwidget example}\label{fig:plotly-basic-example}
\end{figure}
Finally, JavaScript can work together with R to improve how we communicate insights. One of the many ways in which Shiny stands out is that it lets one create web applications solely from R code with no knowledge of HTML, CSS, or JavaScript, but that does not mean they can't extend Shiny---quite the contrary. The \href{http://waiter.john-coene.com/}{waiter package} \citep{R-waiter} integrates a variety of JavaScript libraries to display loading screens in Shiny applications as in Figure \ref{fig:intro-waiter}.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{library}\NormalTok{(shiny)}
\KeywordTok{library}\NormalTok{(waiter)}
\NormalTok{ui <-}\StringTok{ }\KeywordTok{fluidPage}\NormalTok{(}
\KeywordTok{use_waiter}\NormalTok{(), }\CommentTok{# include dependencies}
\KeywordTok{actionButton}\NormalTok{(}\StringTok{"show"}\NormalTok{, }\StringTok{"Show loading for 3 seconds"}\NormalTok{)}
\NormalTok{)}
\NormalTok{server <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(input, output, session)\{}
\CommentTok{# create a waiter}
\NormalTok{ w <-}\StringTok{ }\NormalTok{Waiter}\OperatorTok{$}\KeywordTok{new}\NormalTok{()}
\CommentTok{# on button click}
\KeywordTok{observeEvent}\NormalTok{(input}\OperatorTok{$}\NormalTok{show, \{}
\NormalTok{ w}\OperatorTok{$}\KeywordTok{show}\NormalTok{()}
\KeywordTok{Sys.sleep}\NormalTok{(}\DecValTok{3}\NormalTok{)}
\NormalTok{ w}\OperatorTok{$}\KeywordTok{hide}\NormalTok{()}
\NormalTok{ \})}
\NormalTok{\}}
\KeywordTok{shinyApp}\NormalTok{(ui, server)}
\end{Highlighting}
\end{Shaded}
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/waiter}
}
\caption{Waiter screen}\label{fig:intro-waiter}
\end{figure}
Hopefully this makes a couple of great reasons and alluring examples to entice the reader to persevere with this book.
\hypertarget{intro-methods}{%
\section{Methods}\label{intro-methods}}
Though perhaps not evident at first, all of the packages used as examples in the previous section interfaced with R very differently. As we'll discover, there are many ways in which one can blend JavaScript with R. Generally the way to go about it is dictated by the nature of what is to be achieved.
Let's list the methods available to us to blend JavaScript with R before covering each of them in-depth in their own respective chapter later in the book.
\hypertarget{intro-v8}{%
\subsection{V8}\label{intro-v8}}
\href{https://github.com/jeroen/v8}{V8} by Jeroen Ooms is an R interface to Google's JavaScript engine. It will let you run JavaScript code directly from R and get the result back; it even comes with an interactive console. This is the way the rmapshaper package used in a previous example internally interfaces with the turf.js library.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{library}\NormalTok{(V8)}
\NormalTok{ctx <-}\StringTok{ }\KeywordTok{v8}\NormalTok{()}
\NormalTok{ctx}\OperatorTok{$}\KeywordTok{eval}\NormalTok{(}\StringTok{"2 + 2"}\NormalTok{) }\CommentTok{# this is evaluated in JavaScript!}
\CommentTok{#> [1] "4"}
\end{Highlighting}
\end{Shaded}
\hypertarget{intro-htmlwidgets}{%
\subsection{htmlwidgets}\label{intro-htmlwidgets}}
\href{http://www.htmlwidgets.org/}{htmlwidgets} \citep{R-htmlwidgets} specialises in wrapping JavaScript libraries that generate visual outputs. This is what packages such as plotly, \href{https://rstudio.github.io/DT/}{DT} \citep{R-DT}, \href{http://jkunst.com/highcharter/}{highcharter} \citep{R-highcharter}, and many more use to provide interactive visualisation with R.
It is by far the most popular integration out there: at the time of writing it has been downloaded nearly 10 million times from \index{CRAN}. It will therefore be covered extensively in later chapters.
\hypertarget{intro-shiny}{%
\subsection{Shiny}\label{intro-shiny}}
The Shiny framework allows creating applications accessible from web browsers\index{web browser} where JavaScript natively runs; it follows that JavaScript can run \emph{alongside} such applications. Often overlooked though, the two can also work \emph{hand-in-hand} as one can pass data from the R server to the JavaScript front end and vice versa. This is how the previously-mentioned package waiter internally works with R.
\hypertarget{intro-amiss}{%
\section{Methods Amiss}\label{intro-amiss}}
Note that there are also two other prominent ways one can use JavaScript with R that are not covered in this book. The main reason being that they require significant knowledge of specific JavaScript libraries, d3.js and React, and while these are themselves advanced uses of JavaScript, their integration with R via the following listed packages are relatively straightforward.
\hypertarget{intro-reactr-vuer}{%
\subsection{reactR \& vueR}\label{intro-reactr-vuer}}
\href{https://react-r.github.io/reactR/}{ReactR} \citep{R-reactR} is an R package that emulates very well htmlwidgets but specifically for the \href{https://reactjs.org/}{React\index{React} framework}. Unlike htmlwidgets, it is not limited to visual outputs and also provides functions to build inputs, e.g., a drop-down menu (like \texttt{shiny::selectInput}). The \href{https://glin.github.io/reactable/}{reactable package} \citep{R-reactable} uses reactR to enable building interactive tables solely from R code as shown in Figure \ref{fig:reactable-example}.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{reactable}\OperatorTok{::}\KeywordTok{reactable}\NormalTok{(iris[}\DecValTok{1}\OperatorTok{:}\DecValTok{5}\NormalTok{, ], }\DataTypeTok{showPagination =} \OtherTok{TRUE}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/01-reactable}
}
\caption{reactable package example}\label{fig:reactable-example}
\end{figure}
There is also the package vueR \citep{R-vueR}, which brings some of \index{Vue}Vue to R.
\hypertarget{intro-r2d3}{%
\subsection{r2d3}\label{intro-r2d3}}
\href{https://rstudio.github.io/r2d3/}{r2d3} \citep{R-r2d3} by RStudio is an R package designed specifically to work with \href{https://d3js.org/}{d3.js}. It is similar to htmlwidgets but works rather differently, it allows create visualisations such as Figure \ref{fig:r2d3}.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# https://rstudio.github.io/r2d3/articles/gallery/chord/}
\NormalTok{r2d3}\OperatorTok{::}\KeywordTok{r2d3}\NormalTok{(}
\DataTypeTok{data =} \KeywordTok{matrix}\NormalTok{(}\KeywordTok{round}\NormalTok{(}\KeywordTok{runif}\NormalTok{(}\DecValTok{16}\NormalTok{, }\DecValTok{1}\NormalTok{, }\DecValTok{10000}\NormalTok{)), }\DataTypeTok{ncol =} \DecValTok{4}\NormalTok{, }\DataTypeTok{nrow =} \DecValTok{4}\NormalTok{), }
\DataTypeTok{script =} \StringTok{"chord.js"}
\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/01-d3}
}
\caption{r2d3 basic example}\label{fig:r2d3}
\end{figure}
\hypertarget{prerequisites}{%
\chapter{Prerequisites}\label{prerequisites}}
The code contained in the following pages is approachable to readers with basic knowledge of R. Still, familiarity with package development using \href{https://devtools.r-lib.org/}{devtools} \citep{R-devtools}, the \href{https://shiny.rstudio.com/}{Shiny} framework \citep{R-shiny}, the JSON data format, and JavaScript are essential.
The reason for the former is that some of the ways one builds integrations with JavaScript naturally take the form of R packages. Also, R packages make sharing code, datasets, and anything else R-related extremely convenient, they come with a relatively strict structure, the ability to run unit tests, and much more. These have thus become a core feature of the R ecosystem and, therefore, are used extensively in the book as we create several packages. Therefore, the following section runs over the essentials of building a package to ensure everyone can keep up.
Then we briefly go through the JSON data format as it will be used to a great extent to communicate between R and JavaScript. Since both Shiny and JavaScript run in the browser\index{web browser} they make for axiomatic companions; we'll therefore use Shiny\index{Shiny} extensively. Finally, there is an obligatory short introduction to JavaScript.
It is highly recommended to use the freely available \href{https://rstudio.com/products/rstudio/}{RStudio IDE}\index{RStudio} to follow along as it makes a lot of things easier down the line.
\hypertarget{basics-package-dev}{%
\section{R Package Development}\label{basics-package-dev}}
Developing R packages used to be notoriously tricky, but things have considerably changed in recent years, namely thanks to the devtools \citep{R-devtools}, roxygen2 \citep{R-roxygen2}, and more recent \href{https://usethis.r-lib.org/}{usethis} \citep{R-usethis} packages. Devtools is short for ``developer tools,'' it is specifically designed to help creating packages; setting up tests, running checks, building and installing packages, etc. The second provides an all too convenient way to generate the documentation of packages, and usethis, more broadly, helps setting up projects, and automating repetitive tasks. Here, we only skim over the fundamentals, there is an entire book by Hadley Wickham called \href{http://r-pkgs.had.co.nz/}{\emph{R Packages}} solely dedicated to the topic.
Start by installing those packages from CRAN\index{CRAN} the roxygen2 package does not need to be explicitly installed as it is a dependency\index{dependency} of devtools.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{install.packages}\NormalTok{(}\KeywordTok{c}\NormalTok{(}\StringTok{"devtools"}\NormalTok{, }\StringTok{"usethis"}\NormalTok{))}
\end{Highlighting}
\end{Shaded}
\hypertarget{basics-create-pkg}{%
\subsection{Creating a Package}\label{basics-create-pkg}}
There are multiple ways to create a package. One could manually create every file, use the RStudio IDE\index{RStudio}, or create it from the R console with the usethis \citep{R-usethis} package.
From the RStudio IDE\index{RStudio} go to \texttt{File\ \textgreater{}\ New\ Project\ \textgreater{}\ New\ Directory\ \textgreater{}\ R\ Package} then select ``R package'' and fill in the small form, namely name the package and specify the directory where it should be created, as shown in Figure \ref{fig:rstudio-create-package}.
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/rstudio-create-package}
}
\caption{Package creation wizard}\label{fig:rstudio-create-package}
\end{figure}
But it could be argued that it's actually more accessible from the R console with the usethis package. The \texttt{create\_package} function takes as first argument the path to create the package. If you run it from RStudio\index{RStudio} a new project window should open.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# creates a package named "test" in root of directory.}
\NormalTok{usethis}\OperatorTok{::}\KeywordTok{create_package}\NormalTok{(}\StringTok{"test"}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\begin{verbatim}
β Creating 'test/'
β Setting active project to '/Packages/test'
β Creating 'R/'
β Writing 'DESCRIPTION'
Package: test
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R (parsed):
* First Last <[email protected]> [aut, cre] (YOUR-ORCID-ID)
Description: What the package does (one paragraph).
License: `use_mit_license()`, `use_gpl3_license()` or friends to
pick a license
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.1.9000
β Writing 'NAMESPACE'
β Changing working directory to 'test/'
β Setting active project to '<no active project>'
\end{verbatim}
\hypertarget{basics-metadata}{%
\subsection{Metadata}\label{basics-metadata}}
Every R package includes a \texttt{DESCRIPTION} file which includes metadata about the package. This includes a range of things like the license defining who can use the package, the name of the package, its dependencies\index{dependency}, and more. Below is the default created by the usethis package with \texttt{usethis::create\_package("test")}.
\begin{verbatim}
Package: test
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R:
person(given = "First",
family = "Last",
role = c("aut", "cre"),
email = "[email protected]",
comment = c(ORCID = "YOUR-ORCID-ID"))
Description: What the package does (one paragraph).
License: `use_mit_license()`, `use_gpl3_license()` or friends to
pick a license
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.1.9000
\end{verbatim}
Much of this is outside the scope of the book. However, it is good to grasp how dependencies are specified. As packages are generally intended for sharing with others, it is vital to ensure users of the package meet the dependencies\index{dependency}; otherwise, the package may not work in places. For instance, were we to create a package that relies on one or more functions from the stringr \citep{R-stringr} package we would need to ensure people who install the package have it installed on their machine or those functions will not work.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# R/string.R}
\NormalTok{string_length <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(string) \{}
\NormalTok{ stringr}\OperatorTok{::}\KeywordTok{str_length}\NormalTok{(string)}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
\begin{rmdnote}
Note that the function is preceded by its namespace with \texttt{::}
(more on this later).
\end{rmdnote}
The \texttt{DESCRIPTION} file does this; it will make sure that the dependencies\index{dependency} of the package are met by users who install it. We can specify such dependencies\index{dependency} under \texttt{Imports}, where we can list packages required separated by a comma.
\begin{verbatim}
Imports:
stringr,
dplyr
\end{verbatim}
Then again, the usethis package also allows doing so consistently from the R console, which is great to avoid mishandling the \texttt{DESCRIPTION} file.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# add stringr under Imports}
\NormalTok{usethis}\OperatorTok{::}\KeywordTok{use_package}\NormalTok{(}\StringTok{'stringr'}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
One can also specify another type of dependencies\index{dependency} under \texttt{Suggests}, other packages that enhance the package but are not required to run it. These, unlike package under \texttt{Imports}, are not automatically installed if missing, which can greatly reduce overhead.
\hypertarget{basics-r-code}{%
\subsection{R code}\label{basics-r-code}}
An R package must follow a strict structure. R code must be placed in an \texttt{R/} directory so one should only find \texttt{.R} files in that directory. These files generally contain functions, methods, and R objects.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# R/add.R}
\NormalTok{string_length <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(strings) \{}
\NormalTok{ stringr}\OperatorTok{::}\KeywordTok{str_length}\NormalTok{(strings)}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
\hypertarget{basics-documentation}{%
\subsection{Documentation}\label{basics-documentation}}
Documenting packages used to be notoriously complicated, but thanks to the package roxygen2 that is no longer the case. The documentation of functions of the package (accessible with \texttt{?}) and datasets that comprise the package reside in separate files sitting in the \texttt{man/} directory. These are \texttt{.Rd} files that use a custom syntax resembling LaTex. The roxygen package eases the creation of these files by turning special comments and tags in \texttt{.R} files into said \texttt{.Rd} files.
Special comments are a standard R comment \texttt{\#} followed by an apostrophe \texttt{\textquotesingle{}}. The first sentence of the documentation is the title of the documentation file while the second is the description.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#' Strings Length}
\CommentTok{#' }
\CommentTok{#' Returns the number of characters in strings. }
\NormalTok{string_length <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(strings) \{}
\NormalTok{ stringr}\OperatorTok{::}\KeywordTok{str_length}\NormalTok{(strings)}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
There are a plethora of roxygen2 tags to further document different sections. Below we use two different tags to document the parameters and give an example.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#' Strings Length}
\CommentTok{#' }
\CommentTok{#' Returns the number of characters in strings. }
\CommentTok{#' }
\CommentTok{#' @param strings A vector of character strings.}
\CommentTok{#' }
\CommentTok{#' @example string_length(c("hello", "world"))}
\NormalTok{string_length <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(strings) \{}
\NormalTok{ stringr}\OperatorTok{::}\KeywordTok{str_length}\NormalTok{(strings)}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
As well as generating documentation, the roxygen2 package also allows populating the \texttt{NAMESPACE} file. This is an extensive and often confusing topic, but for this book, we'll be content with the following: the \texttt{NAMESPACE} includes functions that are \emph{imported} and \emph{exported}\index{export} by the package.
By default, functions that are present in the R files in the \texttt{R/} directory are not exported: they are not accessible outside the package. Therefore the \texttt{string\_length} function defined previously will not be made available to users of the package, only other functions within the package will be able to call it. To export it we can use the \texttt{@export} tag\index{export}. This will place the function as exported in the \texttt{NAMESPACE} file.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#' Strings Length}
\CommentTok{#' }
\CommentTok{#' Returns the number of characters in strings. }
\CommentTok{#' }
\CommentTok{#' @param strings A vector of character strings.}
\CommentTok{#' }
\CommentTok{#' @example string_length(c("hello", "world"))}
\CommentTok{#' }
\CommentTok{#' @export}
\NormalTok{string_length <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(strings) \{}
\NormalTok{ stringr}\OperatorTok{::}\KeywordTok{str_length}\NormalTok{(strings)}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
There are two ways to use external functions (functions from other R packages), as done thus far in the \texttt{string\_length} function by using the namespace (package name) to call the function: \texttt{stringr::str\_length}. Or by importing the function needed using a roxygen2 tag thereby removing the need for using the namespace.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#' Strings Length}
\CommentTok{#' }
\CommentTok{#' Returns the number of characters in strings. }
\CommentTok{#' }
\CommentTok{#' @param strings A vector of character strings.}
\CommentTok{#' }
\CommentTok{#' @example string_length(c("hello", "world"))}
\CommentTok{#' }
\CommentTok{#' @importFrom stringr str_length}
\CommentTok{#' }
\CommentTok{#' @export}
\NormalTok{string_length <-}\StringTok{ }\ControlFlowTok{function}\NormalTok{(strings) \{}
\KeywordTok{str_length}\NormalTok{(strings) }\CommentTok{# namespace removed}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
Above we import the function \texttt{str\_length} from the \texttt{stringr} package using the \texttt{importFrom} roxygen2 tag. The first term following the tag is the name of the package wherefrom to import the functions, and the following terms are the name of the functions separated by spaces so one can import multiple functions from the same package with, e.g.: \texttt{@importFrom\ stringr\ str\_length\ str\_to\_upper}. If the package imports many functions from a single package one might also consider importing the package in its entirety with, e.g.: \texttt{@import\ stringr}.
Finally, one can actually generate the \texttt{.Rd} documentation files and populate the \texttt{NAMESPACE} with either the \texttt{devtools::document()} function or \texttt{roxygen2::roxygenise()}.
\begin{rmdnote}
Remember to run \texttt{devtools::document()} after changing roxygen2
tags otherwise changes are not actually reflected in the
\texttt{NAMESPACE} and documentation.
\end{rmdnote}
\hypertarget{basics-installed-files}{%
\subsection{Installed files}\label{basics-installed-files}}
Here we tackle the topic of installed files as it will be relevant to much of what the book covers. Installed files are files that are downloaded and copied as-is when users install the package. This directory will therefore come in very handy to store JavaScript files that package will require. These files can be accessed with the \texttt{system.file} function, which will look for a file from the root of the \texttt{inst/} directory.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# return path to `inst/dependency.js` in `myPackage`}
\NormalTok{path <-}\StringTok{ }\KeywordTok{system.file}\NormalTok{(}\StringTok{"dependency.js"}\NormalTok{, }\DataTypeTok{package =} \StringTok{"myPackage"}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\hypertarget{basics-build-load-install}{%
\subsection{Build, load, and install}\label{basics-build-load-install}}
Finally, after generating the documentation of the package with \texttt{devtools::document()} one can install it locally with \texttt{devtools::install()}. This, however, can take a few seconds too many whilst developing a package as one iterates and regularly tries things; \texttt{devtools::load\_all()} will not install the package but load all the functions and object in the global environment\index{environment} to let you run them.
There is some cyclical nature to developing packages:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
Write some code
\item
Run \texttt{devtools::document()} (if documentation tags have changed)
\item
Run \texttt{devtools::load\_all()}
\item
Repeat
\end{enumerate}
Note whilst this short guide will help you develop packages good enough for your system it will certainly not pass \index{CRAN} checks.
\hypertarget{basics-json}{%
\section{JSON}\label{basics-json}}
JSON\index{JSON} (JavaScript Object Notation) is a prevalent data \emph{interchange} format with which we will work extensively throughout this book; it is thus crucial that we have a good understanding of it before we plunge into the nitty-gritty. As one might foresee, if we want two languages to work together, we must have a data format that can be understood by both---JSON\index{JSON} lets us harmoniously pass data from one to the other. While it is natively supported in JavaScript, it can be graciously handled in R with the \href{https://CRAN.R-project.org/package=jsonlite}{jsonlite package} \citep{R-jsonlite} it is the serialiser used internally by all R packages that we explore in this book.
\begin{rmdnote}
``To serialise''\index{serialise} is just jargon for converting data to
JSON.
\end{rmdnote}
\hypertarget{serialising}{%
\subsection{Serialising}\label{serialising}}
JSON\index{JSON} is to all intents and purposes the equivalent of lists in R; a flexible data format that can store pretty much anything--except data.frames, a structure that does not exist in JavaScript. Below we create a nested list and convert it to JSON\index{JSON} with the help of jsonlite. We set \texttt{pretty} to \texttt{TRUE} to add indentation for cleaner printing, but this is an argument you should omit when writing production code; it will reduce the file size (fewer spaces = smaller file size).
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# install.packages("jsonlite")}
\KeywordTok{library}\NormalTok{(jsonlite)}
\NormalTok{lst <-}\StringTok{ }\KeywordTok{list}\NormalTok{(}
\DataTypeTok{a =} \DecValTok{1}\NormalTok{,}
\DataTypeTok{b =} \KeywordTok{list}\NormalTok{(}
\DataTypeTok{c =} \KeywordTok{c}\NormalTok{(}\StringTok{"A"}\NormalTok{, }\StringTok{"B"}\NormalTok{)}
\NormalTok{ ),}
\DataTypeTok{d =} \DecValTok{1}\OperatorTok{:}\DecValTok{5}
\NormalTok{)}
\KeywordTok{toJSON}\NormalTok{(lst, }\DataTypeTok{pretty =} \OtherTok{TRUE}\NormalTok{)}
\CommentTok{#> \{}
\CommentTok{#> "a": [1],}
\CommentTok{#> "b": \{}
\CommentTok{#> "c": ["A", "B"]}
\CommentTok{#> \},}
\CommentTok{#> "d": [1, 2, 3, 4, 5]}
\CommentTok{#> \}}
\end{Highlighting}
\end{Shaded}
Looking closely at the list and JSON output above, one quickly sees the resemblance. Something seems odd though: the first value in the list (\texttt{a\ =\ 1}) was serialised\index{serialise} to an array (vector) of length one (\texttt{"a":\ {[}1{]}}), where one would probably expect an integer instead, \texttt{1} not \texttt{{[}1{]}}. This is not a mistake; we often forget that there are no scalar types in R and that \texttt{a} is, in fact, a vector as we can observe below.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{x <-}\StringTok{ }\DecValTok{1}
\KeywordTok{length}\NormalTok{(x)}
\CommentTok{#> [1] 1}
\KeywordTok{is.vector}\NormalTok{(x)}
\CommentTok{#> [1] TRUE}
\end{Highlighting}
\end{Shaded}
JavaScript, on the other hand, does have scalar types; more often than not we will want to convert the vectors of length one to scalar types rather than arrays of length one. To do so we need to use the \texttt{auto\_unbox} argument in \texttt{jsonlite::toJSON}; we'll do this most of the time we have to convert data to JSON\index{JSON}.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{toJSON}\NormalTok{(lst, }\DataTypeTok{pretty =} \OtherTok{TRUE}\NormalTok{, }\DataTypeTok{auto_unbox =} \OtherTok{TRUE}\NormalTok{)}
\CommentTok{#> \{}
\CommentTok{#> "a": 1,}
\CommentTok{#> "b": \{}
\CommentTok{#> "c": ["A", "B"]}
\CommentTok{#> \},}
\CommentTok{#> "d": [1, 2, 3, 4, 5]}
\CommentTok{#> \}}
\end{Highlighting}
\end{Shaded}
As demonstrated above the vector of length one was ``unboxed'' into an integer; with \texttt{auto\_unbox} set to \texttt{TRUE}, jsonlite will properly convert such vectors into their appropriate type integer, numeric, boolean, etc. Note that this only applies to vectors lists of length one will be serialised\index{serialise} to arrays of length one even with \texttt{auto\_unbox} turned on: \texttt{list("hello")} will always be converted to \texttt{{[}"hello"{]}}.
\hypertarget{basics-tabular}{%
\subsection{Tabular Data}\label{basics-tabular}}
If JSON is more or less the equivalent of lists in R one might wonder how jsonlite handles dataframes since they do not exist in JavaScript.
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{# subset of built-in dataset}
\NormalTok{df <-}\StringTok{ }\NormalTok{cars[}\DecValTok{1}\OperatorTok{:}\DecValTok{2}\NormalTok{, ]}
\KeywordTok{toJSON}\NormalTok{(df, }\DataTypeTok{pretty =} \OtherTok{TRUE}\NormalTok{)}
\CommentTok{#> [}
\CommentTok{#> \{}
\CommentTok{#> "speed": 4,}
\CommentTok{#> "dist": 2}
\CommentTok{#> \},}
\CommentTok{#> \{}
\CommentTok{#> "speed": 4,}
\CommentTok{#> "dist": 10}
\CommentTok{#> \}}
\CommentTok{#> ]}
\end{Highlighting}
\end{Shaded}
What jsonlite does internally is essentially turn the data.frame into a list \emph{row-wise} to produce a sub-list for every row then it serialises to JSON. This is generally how rectangular data is represented in lists. For instance, \texttt{purrr::transpose} does the same. Another great example is to use \texttt{console.table} in the JavaScript console (more on that later) to display JSON\index{JSON} data as a table (see Figure \ref{fig:console-table}).
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/console-table}
}
\caption{console.table output}\label{fig:console-table}
\end{figure}
We can reproduce this with the snippet below; we remove row names and use apply to turn every row into a list.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{row.names}\NormalTok{(df) <-}\StringTok{ }\OtherTok{NULL}
\NormalTok{df_list <-}\StringTok{ }\KeywordTok{apply}\NormalTok{(df, }\DecValTok{1}\NormalTok{, as.list)}
\KeywordTok{toJSON}\NormalTok{(df_list, }\DataTypeTok{pretty =} \OtherTok{TRUE}\NormalTok{, }\DataTypeTok{auto_unbox =} \OtherTok{TRUE}\NormalTok{)}
\CommentTok{#> [}
\CommentTok{#> \{}
\CommentTok{#> "speed": 4,}
\CommentTok{#> "dist": 2}
\CommentTok{#> \},}
\CommentTok{#> \{}
\CommentTok{#> "speed": 4,}
\CommentTok{#> "dist": 10}
\CommentTok{#> \}}
\CommentTok{#> ]}
\end{Highlighting}
\end{Shaded}
Jsonlite of course also enables reading data from JSON\index{JSON} into R with the function \texttt{fromJSON}.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{json <-}\StringTok{ }\KeywordTok{toJSON}\NormalTok{(df) }\CommentTok{# convert to JSON}
\KeywordTok{fromJSON}\NormalTok{(json) }\CommentTok{# read from JSON}
\CommentTok{#> speed dist}
\CommentTok{#> 1 4 2}
\CommentTok{#> 2 4 10}
\end{Highlighting}
\end{Shaded}
It's important to note that jsonlite did the conversion back to a data frame. Therefore the code below also returns a data frame even though the object we initially converted to JSON\index{JSON} is a list.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{class}\NormalTok{(df_list)}
\CommentTok{#> [1] "list"}
\NormalTok{json <-}\StringTok{ }\KeywordTok{toJSON}\NormalTok{(df_list)}
\KeywordTok{fromJSON}\NormalTok{(json)}
\CommentTok{#> speed dist}
\CommentTok{#> 1 4 2}
\CommentTok{#> 2 4 10}
\end{Highlighting}
\end{Shaded}
Jsonlite provides many more options and functions that will let you tune how JSON data is read and written. Also, the jsonlite package does far more than what we detailed in this section. But at this juncture, this is an adequate understanding of things.
\hypertarget{basics-javascript}{%
\section{JavaScript}\label{basics-javascript}}
The book is not meant to teach JavaScript, only to show how graciously it can work with R. Let us thus go through the very basics to ensure we know enough to get started with the coming chapters.
The easiest way to run JavaScript interactively is probably to create an HTML\index{HTML} file (e.g.: \texttt{try.html}), write your code within a \texttt{\textless{}script\textgreater{}} tag and open the file in your web browser\index{web browser}. The console output can be observed in the console of the browser, developer tools (see Figure \ref{fig:trying-js}).
\begin{Shaded}
\begin{Highlighting}[]
\ErrorTok{<}\NormalTok{!ββ index.html ββ>}
\KeywordTok{<html>}
\KeywordTok{<head>}
\KeywordTok{</head>}
\KeywordTok{<body>}
\KeywordTok{<p}\OtherTok{ id=}\StringTok{"content"}\KeywordTok{>}\NormalTok{Trying JavaScript!}\KeywordTok{</p>}
\KeywordTok{</body>}
\KeywordTok{<script>}
\CommentTok{// place your JavaScript code here}
\VariableTok{console}\NormalTok{.}\AttributeTok{log}\NormalTok{(}\StringTok{'Hello JavaScript!'}\NormalTok{)}
\KeywordTok{</script>}
\KeywordTok{</html>}
\end{Highlighting}
\end{Shaded}
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/tryingjs}
}
\caption{Trying JavaScript}\label{fig:trying-js}
\end{figure}
\hypertarget{basics-chrome-devtools}{%
\subsection{Developer Tools}\label{basics-chrome-devtools}}
Most of the JavaScript code written in this book is intended to be run in web browsers\index{web browser}; it is thus vital that you have a great understanding of your web browser\index{web browser} and its developer tools (devtools). In this section, we discuss those available in Google Chrome and Chromium, but such tools, albeit somewhat different, also exist in Mozilla Firefox and Safari.
\begin{rmdnote}
The RStudio IDE\index{RStudio} is built on Chromium, some of these tools
will therefore also work in RStudio.
\end{rmdnote}
The easiest way to access the developer tools from the browser is by ``inspecting'': right-click on an element on a webpage and select ``inspect.'' This will open the developer tools either at the bottom or on the right (Figure \ref{fig:chrome-devtools}) of the page depending on the defaults.
\begin{figure}[H]
{\centering \includegraphics[width=1\linewidth]{images/devtools}
}
\caption{Google Chrome devtools}\label{fig:chrome-devtools}
\end{figure}
The developer tools pane consists of several tabs but we will mainly use:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
Elements: presents the DOM\index{DOM} Tree, the HTML document structure, great for inspecting the structure of the outputs generated from R.
\item
Console: the JavaScript console where messages, errors, and other such things are logged. Essential for debugging.
\end{enumerate}
\hypertarget{basics-var-scope}{%
\subsection{Variable Declaration and Scope}\label{basics-var-scope}}
One significant way JavaScript differs from R is that variables must be declared using one of three keywords, \texttt{var}, \texttt{let}, or \texttt{const}, which mainly affect the scope\index{scope} where the declared variable will be accessible.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{x }\OperatorTok{=} \DecValTok{1}\OperatorTok{;} \CommentTok{// error}
\KeywordTok{var}\NormalTok{ x }\OperatorTok{=} \DecValTok{1}\OperatorTok{;} \CommentTok{// works}
\end{Highlighting}
\end{Shaded}
One can declare a variable without assigning a value to it, to then do so later on.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{var}\NormalTok{ y}\OperatorTok{;} \CommentTok{// declare }
\NormalTok{y }\OperatorTok{=}\NormalTok{ [}\DecValTok{1}\OperatorTok{,}\DecValTok{2}\OperatorTok{,}\DecValTok{3}\NormalTok{]}\OperatorTok{;} \CommentTok{// define it as array}
\NormalTok{y }\OperatorTok{=} \StringTok{'string'}\OperatorTok{;} \CommentTok{// change to character string}
\end{Highlighting}
\end{Shaded}
The \texttt{let} and \texttt{const} keywords were added in ES2015\index{ECMA}; the \texttt{const} is used to define a constant: a variable that once declared cannot be changed.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{const}\NormalTok{ x }\OperatorTok{=} \DecValTok{1}\OperatorTok{;} \CommentTok{// declare constant}
\NormalTok{x }\OperatorTok{=} \DecValTok{2}\OperatorTok{;} \CommentTok{// error}
\end{Highlighting}
\end{Shaded}
Though this is probably only rarely done in R, one can produce something similar by locking the binding for a variable in its \index{environment}.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{x <-}\StringTok{ }\DecValTok{1} \CommentTok{# declare x}
\KeywordTok{lockBinding}\NormalTok{(}\StringTok{"x"}\NormalTok{, }\DataTypeTok{env =}\NormalTok{ .GlobalEnv) }\CommentTok{# make constant}
\NormalTok{x <-}\StringTok{ }\DecValTok{2} \CommentTok{# error}
\KeywordTok{unlockBinding}\NormalTok{(}\StringTok{"x"}\NormalTok{, }\DataTypeTok{env =}\NormalTok{ .GlobalEnv) }\CommentTok{# unlock binding}
\NormalTok{x <-}\StringTok{ }\DecValTok{2} \CommentTok{# works}
\end{Highlighting}
\end{Shaded}