galaaz 2.1.7 → 2.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/Rakefile +20 -2
  4. data/bin/check_gemfile_lock_version +46 -0
  5. data/bin/release_bump +26 -0
  6. data/blogs/README.md +4 -0
  7. data/blogs/galaaz_2_0/galaaz_2_0.Rmd +385 -0
  8. data/blogs/galaaz_2_0/galaaz_2_0.md +409 -0
  9. data/blogs/galaaz_2_0/galaaz_2_0.tex +756 -0
  10. data/blogs/galaaz_2_0/images/galaaz-header.png +0 -0
  11. data/blogs/galaaz_2_0/images/galaaz-lockup-stacked.png +0 -0
  12. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +76 -58
  13. data/blogs/galaaz_ggplot/galaaz_ggplot.md +188 -161
  14. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +185 -117
  15. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
  16. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
  17. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
  18. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
  19. data/blogs/galaaz_ggplot/images/galaaz-lockup-stacked.png +0 -0
  20. data/blogs/gknit/gknit.Rmd +48 -28
  21. data/blogs/gknit/gknit.md +60 -43
  22. data/blogs/gknit/gknit.tex +1409 -0
  23. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  24. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  25. data/blogs/gknit/gknit_files/figure-latex/bubble-1.png +0 -0
  26. data/blogs/gknit/images/galaaz-lockup-stacked.png +0 -0
  27. data/blogs/manual/images/galaaz-lockup-stacked.png +0 -0
  28. data/blogs/manual/manual.Rmd +161 -71
  29. data/blogs/manual/manual.md +573 -482
  30. data/blogs/manual/manual.tex +1113 -517
  31. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  32. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  33. data/blogs/manual/manual_files/figure-markdown_github/bubble-1.png +0 -0
  34. data/blogs/manual/manual_files/figure-markdown_github/diverging_bar.png +0 -0
  35. data/blogs/nse_dplyr/images/galaaz-lockup-stacked.png +0 -0
  36. data/blogs/nse_dplyr/nse_dplyr.Rmd +42 -8
  37. data/blogs/nse_dplyr/nse_dplyr.md +69 -50
  38. data/blogs/nse_dplyr/nse_dplyr.tex +1626 -0
  39. data/blogs/oh_my/images/galaaz-lockup-stacked.png +0 -0
  40. data/blogs/oh_my/oh_my.Rmd +206 -55
  41. data/blogs/oh_my/oh_my.md +247 -96
  42. data/blogs/oh_my/oh_my.tex +2038 -93
  43. data/blogs/r_on_rails_ledger/images/00_portfolio_page.png +0 -0
  44. data/blogs/r_on_rails_ledger/images/01_results_panel.png +0 -0
  45. data/blogs/r_on_rails_ledger/images/02_density_tail_risk.png +0 -0
  46. data/blogs/r_on_rails_ledger/images/03_mc_cone.png +0 -0
  47. data/blogs/r_on_rails_ledger/images/04_rolling_var.png +0 -0
  48. data/blogs/r_on_rails_ledger/images/galaaz-lockup-stacked.png +0 -0
  49. data/blogs/r_on_rails_ledger/r_on_rails_ledger.Rmd +354 -0
  50. data/blogs/r_on_rails_ledger/r_on_rails_ledger.md +365 -0
  51. data/blogs/r_on_rails_ledger/r_on_rails_ledger.tex +670 -0
  52. data/blogs/ruby_plot/images/galaaz-lockup-stacked.png +0 -0
  53. data/blogs/ruby_plot/ruby_plot.Rmd +56 -35
  54. data/blogs/ruby_plot/ruby_plot.md +63 -47
  55. data/blogs/ruby_plot/ruby_plot.tex +194 -125
  56. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
  57. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
  58. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
  59. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
  60. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
  61. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  62. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  63. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
  64. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
  65. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  66. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  67. data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
  68. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  69. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  70. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  71. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  72. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  73. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  74. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  75. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  76. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  77. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  78. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/dose_len.png +0 -0
  79. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  80. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  81. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  82. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  83. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  84. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  85. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  86. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  87. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  88. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  89. data/lib/galaaz/cli.rb +98 -13
  90. data/logos/icon-font/README.md +27 -0
  91. data/logos/icon-font/build_font.py +130 -0
  92. data/logos/icon-font/galaaz-mark.svg +34 -0
  93. data/script/omarchy/README.md +9 -2
  94. data/script/omarchy/fonts/galaaz.ttf +0 -0
  95. data/script/omarchy/galaaz-guide.sh +1 -1
  96. data/script/omarchy/install-galaaz.sh +8 -1
  97. data/script/omarchy/omarchy-menu.jsonc +21 -9
  98. data/sty/galaaz-header.png +0 -0
  99. data/sty/galaaz-headers-from-p3.tex +4 -0
  100. data/sty/galaaz.sty +76 -23
  101. data/version.rb +1 -1
  102. metadata +46 -7
  103. data/blogs/galaaz_ggplot/galaaz_ggplot.log +0 -754
  104. data/blogs/manual/manual.log +0 -1786
  105. data/blogs/nse_dplyr/nse_dplyr.log +0 -928
  106. data/blogs/oh_my/oh_my.log +0 -804
  107. data/blogs/ruby_plot/ruby_plot.log +0 -885
@@ -0,0 +1,1626 @@
1
+ % Options for packages loaded elsewhere
2
+ \PassOptionsToPackage{unicode}{hyperref}
3
+ \PassOptionsToPackage{hyphens}{url}
4
+ \documentclass[
5
+ 11pt,
6
+ ]{article}
7
+ \usepackage{xcolor}
8
+ \usepackage[margin=1in]{geometry}
9
+ \usepackage{amsmath,amssymb}
10
+ \setcounter{secnumdepth}{5}
11
+ \usepackage{iftex}
12
+ \ifPDFTeX
13
+ \usepackage[T1]{fontenc}
14
+ \usepackage[utf8]{inputenc}
15
+ \usepackage{textcomp} % provide euro and other symbols
16
+ \else % if luatex or xetex
17
+ \usepackage{unicode-math} % this also loads fontspec
18
+ \defaultfontfeatures{Scale=MatchLowercase}
19
+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
20
+ \fi
21
+ \usepackage{lmodern}
22
+ \ifPDFTeX\else
23
+ % xetex/luatex font selection
24
+ \fi
25
+ % Use upquote if available, for straight quotes in verbatim environments
26
+ \IfFileExists{upquote.sty}{\usepackage{upquote}}{}
27
+ \IfFileExists{microtype.sty}{% use microtype if available
28
+ \usepackage[]{microtype}
29
+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
30
+ }{}
31
+ \makeatletter
32
+ \@ifundefined{KOMAClassName}{% if non-KOMA class
33
+ \IfFileExists{parskip.sty}{%
34
+ \usepackage{parskip}
35
+ }{% else
36
+ \setlength{\parindent}{0pt}
37
+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}
38
+ }{% if KOMA class
39
+ \KOMAoptions{parskip=half}}
40
+ \makeatother
41
+ \usepackage{color}
42
+ \usepackage{fancyvrb}
43
+ \newcommand{\VerbBar}{|}
44
+ \newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
45
+ \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
46
+ % Add ',fontsize=\small' for more characters per line
47
+ \usepackage{framed}
48
+ \definecolor{shadecolor}{RGB}{248,248,248}
49
+ \newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}}
50
+ \newcommand{\AlertTok}[1]{\textcolor[rgb]{0.94,0.16,0.16}{#1}}
51
+ \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
52
+ \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{#1}}
53
+ \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
54
+ \newcommand{\BuiltInTok}[1]{#1}
55
+ \newcommand{\CharTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
56
+ \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textit{#1}}}
57
+ \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
58
+ \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}}
59
+ \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
60
+ \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{#1}}
61
+ \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
62
+ \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
63
+ \newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.64,0.00,0.00}{\textbf{#1}}}
64
+ \newcommand{\ExtensionTok}[1]{#1}
65
+ \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
66
+ \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
67
+ \newcommand{\ImportTok}[1]{#1}
68
+ \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
69
+ \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
70
+ \newcommand{\NormalTok}[1]{#1}
71
+ \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.81,0.36,0.00}{\textbf{#1}}}
72
+ \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}}
73
+ \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textit{#1}}}
74
+ \newcommand{\RegionMarkerTok}[1]{#1}
75
+ \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.81,0.36,0.00}{\textbf{#1}}}
76
+ \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
77
+ \newcommand{\StringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
78
+ \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.00,0.00,0.00}{#1}}
79
+ \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
80
+ \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
81
+ \usepackage{graphicx}
82
+ \makeatletter
83
+ \newsavebox\pandoc@box
84
+ \newcommand*\pandocbounded[1]{% scales image to fit in text height/width
85
+ \sbox\pandoc@box{#1}%
86
+ \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%
87
+ \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%
88
+ \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both
89
+ \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%
90
+ \else\usebox{\pandoc@box}%
91
+ \fi%
92
+ }
93
+ % Set default figure placement to htbp
94
+ \def\fps@figure{htbp}
95
+ \makeatother
96
+ \setlength{\emergencystretch}{3em} % prevent overfull lines
97
+ \providecommand{\tightlist}{%
98
+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
99
+ % usar portugues do Brasil
100
+ % \usepackage[brazilian]{babel}
101
+ \usepackage[utf8]{inputenc}
102
+
103
+ \usepackage{geometry}
104
+ \geometry{a4paper, top=1.05in, headheight=30pt, headsep=14pt}
105
+
106
+ % needed for kableExtra
107
+ \usepackage{longtable}
108
+ \usepackage{multirow}
109
+ \usepackage[table]{xcolor}
110
+ \usepackage{wrapfig}
111
+ \usepackage{float}
112
+ \usepackage{colortbl}
113
+ \usepackage{pdflscape}
114
+ \usepackage{tabu}
115
+ \usepackage{threeparttable}
116
+ \usepackage[normalem]{ulem}
117
+
118
+ \usepackage{bbm}
119
+ \usepackage{booktabs}
120
+ \usepackage{expex}
121
+
122
+ \usepackage{graphicx}
123
+
124
+ \usepackage{fancyhdr}
125
+ % Header: small Galaaz mark (left); page number + section title (right),
126
+ % matching classic LaTeX style: "4 AN EXTENSION TO THE EXAMPLE"
127
+ % (upright page number, uppercase italic section name).
128
+ % Logo paths cover repo blogs (../../sty/), installed ~/sty/, and local images/.
129
+ % Blogs may delay headers with \renewcommand{\galaazheaderfrompage}{3} after this sty
130
+ % (e.g. skip title/TOC and a logo splash page).
131
+ \newcommand{\galaazheaderfrompage}{1}
132
+ \newcommand{\galaazheaderlogo}{%
133
+ \raisebox{-0.12\height}{%
134
+ \IfFileExists{../../sty/galaaz-header.png}{%
135
+ \includegraphics[height=0.32in]{../../sty/galaaz-header.png}%
136
+ }{%
137
+ \IfFileExists{galaaz-header.png}{%
138
+ \includegraphics[height=0.32in]{galaaz-header.png}%
139
+ }{%
140
+ \IfFileExists{images/galaaz-header.png}{%
141
+ \includegraphics[height=0.32in]{images/galaaz-header.png}%
142
+ }{}%
143
+ }%
144
+ }%
145
+ }%
146
+ }
147
+ % Section title only in marks (no \thesection); page number is separate.
148
+ \renewcommand{\sectionmark}[1]{\markboth{#1}{}}
149
+ \renewcommand{\subsectionmark}[1]{}% keep the current section in the header
150
+ \newcommand{\galaazmaybeheaderlogo}{%
151
+ \ifnum\value{page}<\galaazheaderfrompage\relax\else\galaazheaderlogo\fi}
152
+ \newcommand{\galaazmayberighthead}{%
153
+ \ifnum\value{page}<\galaazheaderfrompage\relax
154
+ \else
155
+ \textup{\thepage}\hspace{1em}\textit{\MakeUppercase{\leftmark}}%
156
+ \fi
157
+ }
158
+ \pagestyle{fancy}
159
+ \fancyhf{}
160
+ \fancyhead[L]{\galaazmaybeheaderlogo}
161
+ \fancyhead[R]{\galaazmayberighthead}
162
+ \renewcommand{\headrulewidth}{0.3pt}
163
+ \makeatletter
164
+ \renewcommand{\headrule}{%
165
+ \ifnum\value{page}<\galaazheaderfrompage\relax
166
+ \else
167
+ \hrule\@height\headrulewidth\@width\headwidth
168
+ \vskip-\headrulewidth
169
+ \fi
170
+ }
171
+ \makeatother
172
+ % First page often uses plain; same conditional header logic.
173
+ \fancypagestyle{plain}{%
174
+ \fancyhf{}%
175
+ \fancyhead[L]{\galaazmaybeheaderlogo}%
176
+ \fancyhead[R]{\galaazmayberighthead}%
177
+ \renewcommand{\headrulewidth}{0.3pt}%
178
+ }
179
+
180
+ % make available command lastpage
181
+ \usepackage{lastpage}
182
+
183
+ % default fontsize 11pt better to add
184
+ % fontsize on the yaml header
185
+ % \usepackage[fontsize=11pt]{scrextend}
186
+
187
+ % comandos para formatar uma tabela
188
+ \usepackage{array}
189
+ \newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
190
+ \newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
191
+ \newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
192
+
193
+ % necessário if we need to import other latex documents
194
+ \usepackage{import}
195
+
196
+ % Command to import an R variable to latex
197
+ \newcommand{\RtoLatex}[2]{\newcommand{#1}{#2}}
198
+
199
+ % Soft-wrap Pandoc highlighted code/output boxes (Shaded + Highlighting).
200
+ % This runs after Pandoc's default \DefineVerbatimEnvironment{Highlighting}
201
+ % (header includes come later in the generated .tex). Prefer manual line
202
+ % breaks in Rmd sources; breaklines is a safety net for leftovers/output.
203
+ % Requires TinyTeX/TeX Live package: tlmgr install fvextra
204
+ \IfFileExists{fvextra.sty}{%
205
+ \usepackage{fvextra}%
206
+ \DefineVerbatimEnvironment{Highlighting}{Verbatim}{%
207
+ breaklines=true,
208
+ breakanywhere=true,
209
+ breakindent=1.5em,
210
+ fontsize=\small,
211
+ commandchars=\\\{\}%
212
+ }%
213
+ }{%
214
+ % fancyvrb is already loaded by Pandoc; shrink code so more fits per line.
215
+ \DefineVerbatimEnvironment{Highlighting}{Verbatim}{%
216
+ fontsize=\small,
217
+ commandchars=\\\{\}%
218
+ }%
219
+ }
220
+
221
+ %
222
+ %\newcommand{\atraso}[1]{\color{red} \textbf {Tempo desde a Assinatura do Contrato: #1 dias}}
223
+ % No header on title/TOC (p.1) or splash logo page (p.2);
224
+ % logo + page number + section title from page 3 onward.
225
+ % Load after galaaz.sty.
226
+ \renewcommand{\galaazheaderfrompage}{3}
227
+ \usepackage{bookmark}
228
+ \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
229
+ \urlstyle{same}
230
+ \hypersetup{
231
+ pdftitle={Non Standard Evaluation in dplyr with Galaaz},
232
+ pdfauthor={Rodrigo Botafogo; Daniel Mossé - University of Pittsburgh},
233
+ hidelinks,
234
+ pdfcreator={LaTeX via pandoc}}
235
+
236
+ \title{Non Standard Evaluation in dplyr with Galaaz}
237
+ \author{Rodrigo Botafogo \and Daniel Mossé - University of Pittsburgh}
238
+ \date{10/05/2019 (narrative updated for Galaaz 2.0, 2026)}
239
+
240
+ \begin{document}
241
+ \maketitle
242
+
243
+ {
244
+ \setcounter{tocdepth}{2}
245
+ \tableofcontents
246
+ }
247
+ \begin{center}\includegraphics[width=0.45\linewidth]{images/galaaz-lockup-stacked} \end{center}
248
+
249
+ \section{Introduction}\label{introduction}
250
+
251
+ According to Steven Sagaert's answer on Quora about ``Is programming
252
+ language R overrated?'':
253
+
254
+ \begin{quote}
255
+ R is a sophisticated language with an unusual (i.e.~non-mainstream) set
256
+ of features. It`s an impure functional programming language with
257
+ sophisticated metaprogramming and 3 different OO systems.
258
+ \end{quote}
259
+
260
+ \begin{quote}
261
+ Just like common lisp you can completely customise how things work via
262
+ metaprogramming. The biggest example is the tidyverse: by creating it's
263
+ own evaluation system (tidyeval) was able to create a custom syntax for
264
+ dplyr.
265
+ \end{quote}
266
+
267
+ \begin{quote}
268
+ Mastering R (the language) and its ecosystem is not a matter of weeks or
269
+ months but takes years. The rabbit hole goes pretty deep\ldots{}
270
+ \end{quote}
271
+
272
+ Although a highly configurable language can give programmers a great
273
+ deal of power, it can also take years to master---as noted above.
274
+ Programming with \emph{dplyr}, for instance, means learning evaluation
275
+ rules that are not always approachable for \textbf{statisticians and
276
+ analysts who are not full-time software engineers}. That is not a
277
+ criticism: R was \textbf{built} for \textbf{statisticians} who need
278
+ trustworthy results on a deadline, not necessarily for building large
279
+ applications.
280
+
281
+ \textbf{Unfortunately}, when such a user moves on to more
282
+ \textbf{sophisticated} programming patterns, the learning curve can
283
+ become a real hurdle.
284
+
285
+ In this post we will see how to program with \emph{dplyr} in Galaaz and
286
+ how Ruby can simplify the learning curve of mastering \emph{dplyr}
287
+ coding.
288
+
289
+ \section{But first, what is Galaaz??}\label{but-first-what-is-galaaz}
290
+
291
+ Galaaz is a system for tightly coupling Ruby and R. Ruby is a powerful
292
+ language, with a large community, a very large set of libraries and
293
+ great for web development. It is also easy to learn. However, it lacks
294
+ libraries for data science, statistics, scientific plotting and machine
295
+ learning. On the other hand, R is considered one of the most powerful
296
+ languages for solving all of the above problems. \textbf{Python} is a
297
+ strong competitor, with NumPy, pandas, SciPy, scikit-learn, and
298
+ \textbf{many thousands} of other packages on PyPI. We will not dwell on
299
+ R \textbf{versus} Python here: both are excellent languages with
300
+ different strengths. Our interest is to bring to yet another excellent
301
+ language, Ruby, the data science libraries that it lacks.
302
+
303
+ With Galaaz we do not intend to re-implement any of the scientific
304
+ libraries in R. However, we allow for very tight coupling between the
305
+ two languages to the point that the Ruby developer does not need to know
306
+ that there is an R engine running. Also, from the point of view of the R
307
+ user/developer, Galaaz looks a lot like R, with just minor syntactic
308
+ difference, so there is almost no learning curve for the R developer.
309
+ And as we will see in this post that programming with \emph{dplyr} is
310
+ easier in Galaaz than in R.
311
+
312
+ R users are probably quite knowledgeable about \emph{dplyr}. For the
313
+ Ruby developer, \emph{dplyr} and the \emph{tidyverse} libraries are a
314
+ set of libraries for data manipulation in R, developed by Hadley
315
+ Wickham, Chief Scientist at Posit (formerly RStudio) and a prolific R
316
+ coder and writer.
317
+
318
+ For the coupling of Ruby and R, \textbf{Galaaz 2.0} uses
319
+ \textbf{\href{https://www.jruby.org/}{JRuby}} (Ruby on the JVM) together
320
+ with \textbf{GNU R}. A \textbf{bridge} sends expressions and data
321
+ between Ruby and an R process so that Ruby can call \textbf{dplyr} and
322
+ the rest of the tidyverse as if they were part of the same workflow. An
323
+ \textbf{earlier} Galaaz line of work used Oracle's \textbf{GraalVM} with
324
+ \textbf{TruffleRuby} and \textbf{FastR} in a single runtime; that
325
+ approach is \textbf{no longer} the supported stack---see the project
326
+ \textbf{manual} for setup, \textbf{\texttt{bin/galaaz-jruby}}, and
327
+ \textbf{gKnit}.
328
+
329
+ \section{Tidyverse and dplyr}\label{tidyverse-and-dplyr}
330
+
331
+ In
332
+ \href{https://rviews.rstudio.com/2017/06/08/what-is-the-tidyverse/}{What
333
+ is the tidyverse?} the tidyverse is explained as follows:
334
+
335
+ \begin{quote}
336
+ The tidyverse is a coherent system of packages for data manipulation,
337
+ exploration and visualization that share a common design philosophy.
338
+ These were mostly developed by Hadley Wickham himself, but they are now
339
+ being expanded by several contributors. Tidyverse packages are intended
340
+ to make statisticians and data scientists more productive by guiding
341
+ them through workflows that facilitate communication, and result in
342
+ reproducible work products. Fundamentally, the tidyverse is about the
343
+ connections between the tools that make the workflow possible.
344
+ \end{quote}
345
+
346
+ \emph{dplyr} is one of the many packages that are part of the tidyverse.
347
+ It is:
348
+
349
+ \begin{quote}
350
+ a grammar of data manipulation, providing a consistent set of verbs that
351
+ help you solve the most common data manipulation challenges:
352
+ \end{quote}
353
+
354
+ \begin{quote}
355
+ \begin{enumerate}
356
+ \def\labelenumi{\arabic{enumi}.}
357
+ \tightlist
358
+ \item
359
+ mutate() adds new variables that are functions of existing variables
360
+ \item
361
+ select() picks variables based on their names.
362
+ \item
363
+ filter() picks cases based on their values.
364
+ \item
365
+ summarise() reduces multiple values down to a single summary.
366
+ \item
367
+ arrange() changes the ordering of the rows.
368
+ \end{enumerate}
369
+ \end{quote}
370
+
371
+ Very often R is used interactively and users use \emph{dplyr} to
372
+ manipulate a single dataset without programming. When users want to
373
+ replicate their work for multiple datasets, programming becomes
374
+ necessary.
375
+
376
+ \section{Programming with dplyr}\label{programming-with-dplyr}
377
+
378
+ In the vignette
379
+ \href{https://dplyr.tidyverse.org/articles/programming.html}{``Programming
380
+ with dplyr''}, Hadley Wickham states:
381
+
382
+ \begin{quote}
383
+ Most dplyr functions use non-standard evaluation (NSE). This is a
384
+ catch-all term that means they don't follow the usual R rules of
385
+ evaluation. Instead, they capture the expression that you typed and
386
+ evaluate it in a custom way. This has two main benefits for dplyr code:
387
+ \end{quote}
388
+
389
+ \begin{quote}
390
+ Operations on data frames can be expressed succinctly because you don't
391
+ need to repeat the name of the data frame. For example, you can write
392
+ filter(df, x == 1, y == 2, z == 3) instead of df{[}df\$x == 1 \& df\$y
393
+ ==2 \& df\$z == 3, {]}.
394
+ \end{quote}
395
+
396
+ \begin{quote}
397
+ dplyr can choose to compute results in a different way to base R. This
398
+ is important for database backends because dplyr itself doesn't do any
399
+ work, but instead generates the SQL that tells the database what to do.
400
+ \end{quote}
401
+
402
+ But then he goes on:
403
+
404
+ \begin{quote}
405
+ Unfortunately these benefits do not come for free. There are two main
406
+ drawbacks:
407
+ \end{quote}
408
+
409
+ \begin{quote}
410
+ Most dplyr arguments are not referentially transparent. That means you
411
+ can't replace a value with a seemingly equivalent object that you've
412
+ defined elsewhere. In other words, this code:
413
+ \end{quote}
414
+
415
+ \begin{Shaded}
416
+ \begin{Highlighting}[]
417
+ \NormalTok{df }\OtherTok{\textless{}{-}} \FunctionTok{data.frame}\NormalTok{(}\AttributeTok{x =} \DecValTok{1}\SpecialCharTok{:}\DecValTok{3}\NormalTok{, }\AttributeTok{y =} \DecValTok{3}\SpecialCharTok{:}\DecValTok{1}\NormalTok{)}
418
+ \FunctionTok{print}\NormalTok{(}\FunctionTok{filter}\NormalTok{(df, x }\SpecialCharTok{==} \DecValTok{1}\NormalTok{))}
419
+ \CommentTok{\#\textgreater{} \# A tibble: 1 x 2}
420
+ \CommentTok{\#\textgreater{} x y}
421
+ \CommentTok{\#\textgreater{} \textless{}int\textgreater{} \textless{}int\textgreater{}}
422
+ \CommentTok{\#\textgreater{} 1 1 3}
423
+ \end{Highlighting}
424
+ \end{Shaded}
425
+
426
+ \begin{quote}
427
+ Is not equivalent to this code:
428
+ \end{quote}
429
+
430
+ \begin{Shaded}
431
+ \begin{Highlighting}[]
432
+ \NormalTok{my\_var }\OtherTok{\textless{}{-}}\NormalTok{ x}
433
+ \CommentTok{\#\textgreater{} Error in eval(expr, envir, enclos): object \textquotesingle{}x\textquotesingle{} not found}
434
+ \FunctionTok{filter}\NormalTok{(df, my\_var }\SpecialCharTok{==} \DecValTok{1}\NormalTok{)}
435
+ \CommentTok{\#\textgreater{} Error: object \textquotesingle{}my\_var\textquotesingle{} not found}
436
+ \end{Highlighting}
437
+ \end{Shaded}
438
+
439
+ \begin{quote}
440
+ This makes it hard to create functions with arguments that change how
441
+ dplyr verbs are computed.
442
+ \end{quote}
443
+
444
+ As a result of this, programming with \emph{dplyr} requires learning a
445
+ set of new ideas and concepts. In this vignette Hadley goes on showing
446
+ how to program ever more difficult problems with \emph{dplyr}, showing
447
+ the problems it faces and the new concepts needed to solve them.
448
+
449
+ In this blog, we will look at all the problems presented by Harley on
450
+ the vignette and show how those same problems can be solved using Galaaz
451
+ and the Ruby language.
452
+
453
+ This blog is organized as follows: first we show how to write
454
+ expressions using Galaaz.\\
455
+ Expressions are a fundamental concept in \emph{dplyr} and are not part
456
+ of basic Ruby. We extend the Ruby language create a manipulate
457
+ expressions that will be used by \emph{dplyr} functions.
458
+
459
+ Then we show very succintly how Ruby and R can be integrated and how R
460
+ functions are transparently called from Ruby. Galaaz
461
+ \href{https://github.com/rbotafogo/galaaz/wiki}{user manual} (still in
462
+ development) goes in much deeper detail about this integration.
463
+
464
+ Next in section ``Data manipulation wiht \emph{dplyr}'' we go through
465
+ all the problems on the \emph{dplyr} vignette and look at how they are
466
+ solved in Galaaz. We then discuss why programming with Galaaz and
467
+ \emph{dplyr} is easier than programming with \emph{dplyr} in plain R.
468
+
469
+ The following section looks at another more advanced problem and shows
470
+ that Galaaz can still handle it without any difficulty. We then provide
471
+ further reading and concluding remarks.
472
+
473
+ \section{Writing Expressions in
474
+ Galaaz}\label{writing-expressions-in-galaaz}
475
+
476
+ Galaaz extends Ruby to work with expressions, similar to R's expressions
477
+ build with `quote' (base R) or `quo' (tidyverse). Expressions in this
478
+ context are like mathematical expressions or formulae. For instance, in
479
+ mathematics, the expression \(y = sin(x)\) describes a function but
480
+ cannot be computed unless the value of \(x\) is bound to some value.
481
+
482
+ Expressions are fundamental in \emph{dplyr} programming as they are the
483
+ input to \emph{dplyr} functions, for instance, as we will see shortly,
484
+ if a data frame has a column named `x' and we want to add another
485
+ column, y, to this dataframe that has the values of `x' times 2, then we
486
+ would call a \emph{dplyr} function with the expression `y = x * 2'.
487
+
488
+ \subsection{A note on notation}\label{a-note-on-notation}
489
+
490
+ This blog was written in Rmarkdown and automatically converted to HTML
491
+ or PDF (depending on where you are reading this blog) with gKnit (a tool
492
+ provided by Galaaz). In Rmarkdown, it is possible to write text and code
493
+ blocks that are executed to generate the final report. Code blocks
494
+ appear inside a `box' and the result of their execution appear either in
495
+ another type of `box' with a different background (HTML) or as normal
496
+ text (PDF). Every output line from the code execution is preceded by
497
+ `\#\#'.
498
+
499
+ \subsection{Expressions from
500
+ operators}\label{expressions-from-operators}
501
+
502
+ The code below creates an expression summing two symbols. Note that :a
503
+ and :b are Ruby symbols and are not bound to any values at the time of
504
+ expression definition:
505
+
506
+ \begin{Shaded}
507
+ \begin{Highlighting}[]
508
+ \ControlFlowTok{begin}
509
+ \NormalTok{ exp1 }\OperatorTok{=} \WarningTok{:a} \OperatorTok{+} \WarningTok{:b}
510
+ \FunctionTok{puts}\NormalTok{ exp1}
511
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
512
+ \CommentTok{\# Bare Symbol\#+ is not expression sugar in Galaaz 2.0; short error for PDF.}
513
+ \FunctionTok{puts} \StringTok{"}\SpecialCharTok{\#\{}\NormalTok{e}\AttributeTok{.class}\SpecialCharTok{\}}\StringTok{: }\SpecialCharTok{\#\{}\NormalTok{e}\AttributeTok{.message}\SpecialCharTok{\}}\StringTok{"}
514
+ \ControlFlowTok{end}
515
+ \end{Highlighting}
516
+ \end{Shaded}
517
+
518
+ \begin{verbatim}
519
+ ## NoMethodError: undefined method '+' for an instance of Symbol
520
+ \end{verbatim}
521
+
522
+ In Galaaz, we can build any complex mathematical expression such as:
523
+
524
+ \begin{Shaded}
525
+ \begin{Highlighting}[]
526
+ \NormalTok{exp2 }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{) }\OperatorTok{*} \FloatTok{2.0} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:c}\KeywordTok{]} \OperatorTok{**} \DecValTok{2} \OperatorTok{/} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]}
527
+ \FunctionTok{puts}\NormalTok{ exp2}
528
+ \end{Highlighting}
529
+ \end{Shaded}
530
+
531
+ \begin{verbatim}
532
+ ## a + b * 2.0 + c ^ 2L / z
533
+ \end{verbatim}
534
+
535
+ Expressions are printed with the same format as the equivalent R
536
+ expressions. The `L' after 2 indicates that 2 is an integer.
537
+
538
+ The R developer should note that in R, if she writes the number `2', the
539
+ R interpreter will convert it to float. In order to get an interger she
540
+ should write `2L'. Galaaz follows Ruby notation and `2' is an integer,
541
+ while `2.0' is a float.
542
+
543
+ It is also possible to use inequality operators in building expressions:
544
+
545
+ \begin{Shaded}
546
+ \begin{Highlighting}[]
547
+ \NormalTok{exp3 }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{) }\OperatorTok{\textgreater{}=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]}
548
+ \FunctionTok{puts}\NormalTok{ exp3}
549
+ \end{Highlighting}
550
+ \end{Shaded}
551
+
552
+ \begin{verbatim}
553
+ ## a + b >= z
554
+ \end{verbatim}
555
+
556
+ Expressions' definition can also make use of normal Ruby variables
557
+ without any problem:
558
+
559
+ \begin{Shaded}
560
+ \begin{Highlighting}[]
561
+ \NormalTok{x }\OperatorTok{=} \DecValTok{20}
562
+ \NormalTok{y }\OperatorTok{=} \FloatTok{30.0}
563
+ \NormalTok{exp\_var }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{) }\OperatorTok{*}\NormalTok{ x }\OperatorTok{\textless{}=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]} \OperatorTok{{-}}\NormalTok{ y}
564
+ \FunctionTok{puts}\NormalTok{ exp\_var}
565
+ \end{Highlighting}
566
+ \end{Shaded}
567
+
568
+ \begin{verbatim}
569
+ ## a + b * 20L <= z - 30.0
570
+ \end{verbatim}
571
+
572
+ Galaaz provides both symbolic representations for operators, such as
573
+ (\textgreater, \textless, !=) as functional notation for those operators
574
+ such as (.gt, .ge, etc.). So the same expression written above can also
575
+ be written as
576
+
577
+ \begin{Shaded}
578
+ \begin{Highlighting}[]
579
+ \NormalTok{exp4 }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{)}\AttributeTok{.ge} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]}
580
+ \FunctionTok{puts}\NormalTok{ exp4}
581
+ \end{Highlighting}
582
+ \end{Shaded}
583
+
584
+ \begin{verbatim}
585
+ ## a + b >= z
586
+ \end{verbatim}
587
+
588
+ Two types of expressions, however, can only be created with the
589
+ functional representation of the operators. Those are expressions
590
+ involving `==', and `='. This is the case since those symbols have
591
+ special meaning in Ruby and should not be redefined.
592
+
593
+ In order to write an expression involving `==' we need to use the method
594
+ `.eq' and for `=' we need the function `.assign':
595
+
596
+ \begin{Shaded}
597
+ \begin{Highlighting}[]
598
+ \NormalTok{exp5 }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{)}\AttributeTok{.eq} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]}
599
+ \FunctionTok{puts}\NormalTok{ exp5}
600
+ \end{Highlighting}
601
+ \end{Shaded}
602
+
603
+ \begin{verbatim}
604
+ ## a + b == z
605
+ \end{verbatim}
606
+
607
+ \begin{Shaded}
608
+ \begin{Highlighting}[]
609
+ \NormalTok{exp6 }\OperatorTok{=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:y}\KeywordTok{]}\AttributeTok{.assign} \ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}
610
+ \FunctionTok{puts}\NormalTok{ exp6}
611
+ \end{Highlighting}
612
+ \end{Shaded}
613
+
614
+ \begin{verbatim}
615
+ ## y <- a + b
616
+ \end{verbatim}
617
+
618
+ Users should be careful when writing expressions not to inadvertently
619
+ use `==' or `=' as this will generate an error, that might be a bit
620
+ cryptic (in future releases of Galaza, we plan to improve the error
621
+ message).
622
+
623
+ \begin{Shaded}
624
+ \begin{Highlighting}[]
625
+ \NormalTok{exp\_wrong }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{) }\OperatorTok{==} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]}
626
+ \FunctionTok{puts}\NormalTok{ exp\_wrong}
627
+ \end{Highlighting}
628
+ \end{Shaded}
629
+
630
+ \begin{verbatim}
631
+ ## false
632
+ \end{verbatim}
633
+
634
+ The problem lies with the fact that when using `==' we are comparing
635
+ expression (R{[}:a{]} + R{[}:b{]}) to expression R{[}:z{]} with `=='.
636
+ When this comparison is executed, the system tries to evaluate :a, :b
637
+ and :z, and those symbols, at this time, are not bound to anything
638
+ giving the ``object `a' not found'' message.
639
+
640
+ \subsection{Expressions with R
641
+ methods}\label{expressions-with-r-methods}
642
+
643
+ It is often necessary to create an expression that uses a method or
644
+ function. For instance, in mathematics, it's quite natural to write an
645
+ expressin such as \(y = sin(x)\). In this case, the `sin' function is
646
+ part of the expression and should not be immediately executed. When we
647
+ want the function to be part of the expression, we call the function
648
+ preceeding it by the letter E, such as `E.sin(x)'
649
+
650
+ \begin{Shaded}
651
+ \begin{Highlighting}[]
652
+ \NormalTok{exp7 }\OperatorTok{=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:y}\KeywordTok{]}\AttributeTok{.assign} \ConstantTok{E}\AttributeTok{.sin}\NormalTok{(}\ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\NormalTok{)}
653
+ \FunctionTok{puts}\NormalTok{ exp7}
654
+ \end{Highlighting}
655
+ \end{Shaded}
656
+
657
+ \begin{verbatim}
658
+ ## y <- sin(x)
659
+ \end{verbatim}
660
+
661
+ Function expressions can also be written using `.' notation:
662
+
663
+ \begin{Shaded}
664
+ \begin{Highlighting}[]
665
+ \NormalTok{exp8 }\OperatorTok{=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:y}\KeywordTok{]}\AttributeTok{.assign} \ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\AttributeTok{.sin}
666
+ \FunctionTok{puts}\NormalTok{ exp8}
667
+ \end{Highlighting}
668
+ \end{Shaded}
669
+
670
+ \begin{verbatim}
671
+ ## y <- sin(x)
672
+ \end{verbatim}
673
+
674
+ When a function has multiple arguments, the first one can be used before
675
+ the `.'. For instance, the R concatenate function `c', that concatenates
676
+ two or more arguments can be part of an expression as:
677
+
678
+ \begin{Shaded}
679
+ \begin{Highlighting}[]
680
+ \NormalTok{exp9 }\OperatorTok{=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\AttributeTok{.c}\NormalTok{(}\ConstantTok{R}\KeywordTok{[}\WarningTok{:y}\KeywordTok{]}\NormalTok{)}
681
+ \FunctionTok{puts}\NormalTok{ exp9}
682
+ \end{Highlighting}
683
+ \end{Shaded}
684
+
685
+ \begin{verbatim}
686
+ ## c(x, y)
687
+ \end{verbatim}
688
+
689
+ Note that this gives an OO feeling to the code, as if we were saying `x'
690
+ concatenates `y'. As a side note, `.' notation can be used as the R pipe
691
+ operator `\%\textgreater\%', but is more general than the pipe.
692
+
693
+ \subsection{Evaluating an Expression}\label{evaluating-an-expression}
694
+
695
+ Although we are mainly focusing on expressions to pass them to
696
+ \emph{dplyr} functions, expressions can be evaluated by calling function
697
+ `eval' with a binding.
698
+
699
+ A binding can be provided with a list or a data frame as shown below:
700
+
701
+ \begin{Shaded}
702
+ \begin{Highlighting}[]
703
+ \NormalTok{exp }\OperatorTok{=}\NormalTok{ (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{) }\OperatorTok{*} \FloatTok{2.0} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:c}\KeywordTok{]} \OperatorTok{**} \DecValTok{2} \OperatorTok{/} \ConstantTok{R}\KeywordTok{[}\WarningTok{:z}\KeywordTok{]}
704
+ \FunctionTok{puts}\NormalTok{ exp}\AttributeTok{.eval}\NormalTok{(}\ConstantTok{R}\AttributeTok{.list}\NormalTok{(}\WarningTok{a:} \DecValTok{10}\NormalTok{, }\WarningTok{b:} \DecValTok{20}\NormalTok{, }\WarningTok{c:} \DecValTok{30}\NormalTok{, }\WarningTok{z:} \DecValTok{40}\NormalTok{))}
705
+ \end{Highlighting}
706
+ \end{Shaded}
707
+
708
+ \begin{verbatim}
709
+ ## [1] 72.5
710
+ \end{verbatim}
711
+
712
+ with a data frame:
713
+
714
+ \begin{Shaded}
715
+ \begin{Highlighting}[]
716
+ \NormalTok{df }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.data\_\_frame}\NormalTok{(}
717
+ \WarningTok{a:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{3}\NormalTok{),}
718
+ \WarningTok{b:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{10}\NormalTok{, }\DecValTok{20}\NormalTok{, }\DecValTok{30}\NormalTok{),}
719
+ \WarningTok{c:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{100}\NormalTok{, }\DecValTok{200}\NormalTok{, }\DecValTok{300}\NormalTok{),}
720
+ \WarningTok{z:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1000}\NormalTok{, }\DecValTok{2000}\NormalTok{, }\DecValTok{3000}\NormalTok{))}
721
+
722
+ \FunctionTok{puts}\NormalTok{ exp}\AttributeTok{.eval}\NormalTok{(df)}
723
+ \end{Highlighting}
724
+ \end{Shaded}
725
+
726
+ \begin{verbatim}
727
+ ## [1] 31 62 93
728
+ \end{verbatim}
729
+
730
+ \section{Using Galaaz to call R
731
+ functions}\label{using-galaaz-to-call-r-functions}
732
+
733
+ Galaaz tries to emulate as closely as possible the way R functions are
734
+ called and migrating from R to Galaaz should be quite easy requiring
735
+ only minor syntactic changes to an R script. In this post, we do not
736
+ have enough space to write a complete manual on Galaaz (a short manual
737
+ can be found at: \url{https://www.rubydoc.info/gems/galaaz/0.4.9}), so
738
+ we will present only a few examples scripts using Galaaz.
739
+
740
+ Basically, to call an R function from Ruby with Galaaz, one only needs
741
+ to preced the function with `R.'. For instance, to create a vector in R,
742
+ the `c' function is used. In Galaaz, a vector can be created by using
743
+ `R.c':
744
+
745
+ \begin{Shaded}
746
+ \begin{Highlighting}[]
747
+ \NormalTok{vec }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\FloatTok{1.0}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{3}\NormalTok{)}
748
+ \FunctionTok{puts}\NormalTok{ vec}
749
+ \end{Highlighting}
750
+ \end{Shaded}
751
+
752
+ \begin{verbatim}
753
+ ## [1] 1 2 3
754
+ \end{verbatim}
755
+
756
+ A list is created in R with the `list' function, so in Galaaz we do:
757
+
758
+ \begin{Shaded}
759
+ \begin{Highlighting}[]
760
+ \NormalTok{list }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.list}\NormalTok{(}\WarningTok{a:} \FloatTok{1.0}\NormalTok{, }\WarningTok{b:} \DecValTok{2}\NormalTok{, }\WarningTok{c:} \DecValTok{3}\NormalTok{)}
761
+ \FunctionTok{puts}\NormalTok{ list}
762
+ \end{Highlighting}
763
+ \end{Shaded}
764
+
765
+ \begin{verbatim}
766
+ ## $a
767
+ ## [1] 1
768
+ ##
769
+ ## $b
770
+ ## [1] 2
771
+ ##
772
+ ## $c
773
+ ## [1] 3
774
+ \end{verbatim}
775
+
776
+ Note that we can use named arguments in our list. The same code in R
777
+ would be:
778
+
779
+ \begin{Shaded}
780
+ \begin{Highlighting}[]
781
+ \NormalTok{lst }\OtherTok{=} \FunctionTok{list}\NormalTok{(}\AttributeTok{a =} \DecValTok{1}\NormalTok{, }\AttributeTok{b =} \DecValTok{2}\DataTypeTok{L}\NormalTok{, }\AttributeTok{c =} \DecValTok{3}\DataTypeTok{L}\NormalTok{)}
782
+ \FunctionTok{print}\NormalTok{(lst)}
783
+ \end{Highlighting}
784
+ \end{Shaded}
785
+
786
+ \begin{verbatim}
787
+ ## $a
788
+ ## [1] 1
789
+ ##
790
+ ## $b
791
+ ## [1] 2
792
+ ##
793
+ ## $c
794
+ ## [1] 3
795
+ \end{verbatim}
796
+
797
+ Now, let's say that `x' is an angle of 45\(^\circ\) and we acttually
798
+ want to create the expression \(y = sin(45^\circ)\), which is
799
+ \(y = 0.850...\). In this case, we will use `R.sin':
800
+
801
+ \begin{Shaded}
802
+ \begin{Highlighting}[]
803
+ \NormalTok{exp10 }\OperatorTok{=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:y}\KeywordTok{]}\AttributeTok{.assign} \ConstantTok{R}\AttributeTok{.sin}\NormalTok{(}\DecValTok{45}\NormalTok{)}
804
+ \FunctionTok{puts}\NormalTok{ exp10}
805
+ \end{Highlighting}
806
+ \end{Shaded}
807
+
808
+ \begin{verbatim}
809
+ ## y <- 0.850903524534118
810
+ \end{verbatim}
811
+
812
+ \section{\texorpdfstring{Data manipulation wiht
813
+ \emph{dplyr}}{Data manipulation wiht dplyr}}\label{data-manipulation-wiht-dplyr}
814
+
815
+ In this section we will give a brief tour \emph{dplyr}'s usage in Galaaz
816
+ and how to manipulate data in Ruby with it. This section will follow
817
+ \href{https://dplyr.tidyverse.org/articles/dplyr.html}{\emph{dplyr}'s
818
+ vignette} that explores the nycflights13 data set. This dataset contains
819
+ all 336776 flights that departed from New York City in 2013. The data
820
+ comes from the US Bureau of Transportation Statistics.
821
+
822
+ Let's start by taking a look at this dataset:
823
+
824
+ \begin{Shaded}
825
+ \begin{Highlighting}[]
826
+ \ConstantTok{R}\AttributeTok{.library}\NormalTok{(}\VerbatimStringTok{\textquotesingle{}nycflights13\textquotesingle{}}\NormalTok{)}
827
+ \CommentTok{\# check it\textquotesingle{}s dimension}
828
+ \FunctionTok{puts} \OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:flights}\KeywordTok{]}\AttributeTok{.dim}
829
+ \CommentTok{\# and the structure}
830
+ \OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:flights}\KeywordTok{]}\AttributeTok{.str}
831
+ \end{Highlighting}
832
+ \end{Shaded}
833
+
834
+ \begin{verbatim}
835
+ ## ~(dim(flights))
836
+ ## <environment: 0x5acac1752f98>
837
+ \end{verbatim}
838
+
839
+ Now, let's use a first verb of \emph{dplyr}: `filter'. This verb,
840
+ obviously, will filter the data by the given expression. In the next
841
+ block, we filter by columns `month' and `day'. The first argument to the
842
+ filter function is symbol `:flights'. A Ruby symbol, when given to an R
843
+ function will convert to the R variable of the same name, in this case
844
+ `flights', that holds the nycflights13 data frame.
845
+
846
+ The second and third arguments are expressions that will be used by the
847
+ filter function to filter by columns, looking for entries in which the
848
+ month and day are equal to 1.
849
+
850
+ \begin{Shaded}
851
+ \begin{Highlighting}[]
852
+ \FunctionTok{puts} \ConstantTok{R}\AttributeTok{.filter}\NormalTok{(}\WarningTok{:flights}\NormalTok{, (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:month}\KeywordTok{]}\AttributeTok{.eq} \DecValTok{1}\NormalTok{), (}\ConstantTok{R}\KeywordTok{[}\WarningTok{:day}\KeywordTok{]}\AttributeTok{.eq} \DecValTok{1}\NormalTok{))}
853
+ \end{Highlighting}
854
+ \end{Shaded}
855
+
856
+ \begin{verbatim}
857
+ ## # A tibble: 842 x 19
858
+ ## year month day dep_time sched_dep_time dep_delay arr_time
859
+ ## <int> <int> <int> <int> <int> <dbl> <int>
860
+ ## 1 2013 1 1 517 515 2 830
861
+ ## 2 2013 1 1 533 529 4 850
862
+ ## 3 2013 1 1 542 540 2 923
863
+ ## 4 2013 1 1 544 545 -1 1004
864
+ ## 5 2013 1 1 554 600 -6 812
865
+ ## 6 2013 1 1 554 558 -4 740
866
+ ## 7 2013 1 1 555 600 -5 913
867
+ ## 8 2013 1 1 557 600 -3 709
868
+ ## 9 2013 1 1 557 600 -3 838
869
+ ## 10 2013 1 1 558 600 -2 753
870
+ ## # i 832 more rows
871
+ ## # i 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
872
+ ## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
873
+ ## # dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
874
+ ## # minute <dbl>, time_hour <dttm>
875
+ \end{verbatim}
876
+
877
+ \subsection{\texorpdfstring{Programming with \emph{dplyr}: problems and
878
+ how to solve them in
879
+ Galaaz}{Programming with dplyr: problems and how to solve them in Galaaz}}\label{programming-with-dplyr-problems-and-how-to-solve-them-in-galaaz}
880
+
881
+ In this section we look at the list of problems that Hadley describes in
882
+ the ``Programming with dplyr'' vignette and show how those problems are
883
+ solved and coded with Galaaz. Readers interested in how those problems
884
+ are treated in \emph{dplyr} should read the vignette and use it as a
885
+ comparison with this blog.
886
+
887
+ \subsection{Filtering using
888
+ expressions}\label{filtering-using-expressions}
889
+
890
+ Now that we know how to write expressions and call R functions, let's do
891
+ some data manipulation in Galaaz. Let's first start by creating a data
892
+ frame. In R, the `data.frame' function creates a data frame. In Ruby,
893
+ writing `data.frame' will not parse as a single object. To call R
894
+ functions that have a `.' in them, we need to substitute the `.' with
895
+ '\_\_`. So, method 'data.frame' in R, is called in Galaaz as
896
+ `R.data\_\_frame':
897
+
898
+ \begin{Shaded}
899
+ \begin{Highlighting}[]
900
+ \NormalTok{df }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.data\_\_frame}\NormalTok{(}\WarningTok{x:}\NormalTok{ (}\DecValTok{1}\OperatorTok{..}\DecValTok{3}\NormalTok{), }\WarningTok{y:}\NormalTok{ (}\DecValTok{3}\OperatorTok{..}\DecValTok{1}\NormalTok{))}
901
+ \FunctionTok{puts}\NormalTok{ df}
902
+ \end{Highlighting}
903
+ \end{Shaded}
904
+
905
+ \begin{verbatim}
906
+ ## x y
907
+ ## 1 1 3
908
+ ## 2 2 2
909
+ ## 3 3 1
910
+ \end{verbatim}
911
+
912
+ \emph{dplyr} provides the `filter' function, that filters data in a data
913
+ brame. The `filter' function can be called on this data frame either by
914
+ using `R.filter(df, \ldots)' or by using dot notation.
915
+
916
+ -------FIX---------
917
+
918
+ We prefer to use dot notation as shown below. The argument to `filter'
919
+ should be an expression. Note that if we gave to filter a Ruby
920
+ expression such as `x == 1', we would get an error, since there is no
921
+ variable `x' defined and if `x' was a variable then `x == 1' would
922
+ either be `true' or `false'. Our goal is to filter our data frame
923
+ returning all rows in which the `x' value is equal to 1. To express this
924
+ we want: `R{[}:x{]}.eq 1', where :x will be interpreted by filter as the
925
+ `x' column.
926
+
927
+ \begin{Shaded}
928
+ \begin{Highlighting}[]
929
+ \FunctionTok{puts}\NormalTok{ df}\AttributeTok{.filter}\NormalTok{(}\ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\AttributeTok{.eq} \DecValTok{1}\NormalTok{)}
930
+ \end{Highlighting}
931
+ \end{Shaded}
932
+
933
+ \begin{verbatim}
934
+ ## x y
935
+ ## 1 1 3
936
+ \end{verbatim}
937
+
938
+ In R, and when coding with `tidyverse', arguments to a function are
939
+ usually not \emph{referencially transparent}. That is, you can't replace
940
+ a value with a seemingly equivalent object that you've defined
941
+ elsewhere. In other words, this code
942
+
943
+ \begin{Shaded}
944
+ \begin{Highlighting}[]
945
+ \NormalTok{my\_var }\OtherTok{\textless{}{-}}\NormalTok{ x}
946
+ \FunctionTok{filter}\NormalTok{(df, my\_var }\SpecialCharTok{==} \DecValTok{1}\NormalTok{)}
947
+ \end{Highlighting}
948
+ \end{Shaded}
949
+
950
+ Generates the following error: ``object `x' not found.
951
+
952
+ However, in Galaaz, arguments are referencially transparent as can be
953
+ seen by the code below. Note initially that `my\_var = R{[}:x{]}' will
954
+ not give the error ``object `x' not found'' since `:x' is treated as an
955
+ expression and assigned to my\_var. Then when doing (my\_var.eq 1),
956
+ my\_var is a variable that resolves to `:x' and it becomes equivalent to
957
+ (R{[}:x{]}.eq 1) which is what we want.
958
+
959
+ \begin{Shaded}
960
+ \begin{Highlighting}[]
961
+ \NormalTok{my\_var }\OperatorTok{=} \ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}
962
+ \FunctionTok{puts}\NormalTok{ df}\AttributeTok{.filter}\NormalTok{(my\_var}\AttributeTok{.eq} \DecValTok{1}\NormalTok{)}
963
+ \end{Highlighting}
964
+ \end{Shaded}
965
+
966
+ \begin{verbatim}
967
+ ## x y
968
+ ## 1 1 3
969
+ \end{verbatim}
970
+
971
+ As stated by Hadley
972
+
973
+ \begin{quote}
974
+ dplyr code is ambiguous. Depending on what variables are defined where,
975
+ filter(df, x == y) could be equivalent to any of:
976
+ \end{quote}
977
+
978
+ \begin{verbatim}
979
+ df[df$x == df$y, ]
980
+ df[df$x == y, ]
981
+ df[x == df$y, ]
982
+ df[x == y, ]
983
+ \end{verbatim}
984
+
985
+ In galaaz this ambiguity does not exist, filter(df, x.eq y) is not a
986
+ valid expression as expressions are build with symbols. In doing
987
+ filter(df, R{[}:x{]}.eq y) we are looking for elements of the `x' column
988
+ that are equal to a previously defined y variable. Finally in filter(df,
989
+ R{[}:x{]}.eq R{[}:y{]}) we are looking for elements in which the `x'
990
+ column value is equal to the `y' column value. This can be seen in the
991
+ following two chunks of code:
992
+
993
+ \begin{Shaded}
994
+ \begin{Highlighting}[]
995
+ \NormalTok{y }\OperatorTok{=} \DecValTok{1}
996
+ \NormalTok{x }\OperatorTok{=} \DecValTok{2}
997
+
998
+ \CommentTok{\# looking for values where the \textquotesingle{}x\textquotesingle{} column is equal to the \textquotesingle{}y\textquotesingle{} column}
999
+ \FunctionTok{puts}\NormalTok{ df}\AttributeTok{.filter}\NormalTok{(}\ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\AttributeTok{.eq} \ConstantTok{R}\KeywordTok{[}\WarningTok{:y}\KeywordTok{]}\NormalTok{)}
1000
+ \end{Highlighting}
1001
+ \end{Shaded}
1002
+
1003
+ \begin{verbatim}
1004
+ ## x y
1005
+ ## 1 2 2
1006
+ \end{verbatim}
1007
+
1008
+ \begin{Shaded}
1009
+ \begin{Highlighting}[]
1010
+ \CommentTok{\# looking for values where the \textquotesingle{}x\textquotesingle{} column is equal to the \textquotesingle{}y\textquotesingle{} variable}
1011
+ \CommentTok{\# in this case, the number 1}
1012
+ \FunctionTok{puts}\NormalTok{ df}\AttributeTok{.filter}\NormalTok{(}\ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\AttributeTok{.eq}\NormalTok{ y)}
1013
+ \end{Highlighting}
1014
+ \end{Shaded}
1015
+
1016
+ \begin{verbatim}
1017
+ ## x y
1018
+ ## 1 1 3
1019
+ \end{verbatim}
1020
+
1021
+ \subsection{Writing a function that applies to different data
1022
+ sets}\label{writing-a-function-that-applies-to-different-data-sets}
1023
+
1024
+ Let's suppose that we want to write a function that receives as the
1025
+ first argument a data frame and as second argument an expression that
1026
+ adds a column to the data frame that is equal to the sum of elements in
1027
+ column `a' plus `x'.
1028
+
1029
+ Here is the intended behaviour using the `mutate' function of `dplyr':
1030
+
1031
+ \begin{verbatim}
1032
+ mutate(df1, y = a + x)
1033
+ mutate(df2, y = a + x)
1034
+ mutate(df3, y = a + x)
1035
+ mutate(df4, y = a + x)
1036
+ \end{verbatim}
1037
+
1038
+ The naive approach to writing an R function to solve this problem is:
1039
+
1040
+ \begin{verbatim}
1041
+ mutate_y <- function(df) {
1042
+ mutate(df, y = a + x)
1043
+ }
1044
+ \end{verbatim}
1045
+
1046
+ Unfortunately, in R, this function can fail silently if one of the
1047
+ variables isn't present in the data frame, but is present in the global
1048
+ environment. We will not go through here how to solve this problem in R.
1049
+
1050
+ In Galaaz the method mutate\_y below will work fine and will never fail
1051
+ silently.
1052
+
1053
+ \begin{Shaded}
1054
+ \begin{Highlighting}[]
1055
+ \ControlFlowTok{def}\NormalTok{ mutate\_y(df)}
1056
+ \CommentTok{\# Column names are Ruby kwargs (y: …).}
1057
+ \CommentTok{\# Use .assign only for R \textasciigrave{}\textless{}{-}\textasciigrave{} expressions.}
1058
+ \NormalTok{ df}\AttributeTok{.mutate}\NormalTok{(}\WarningTok{y:} \ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{+} \ConstantTok{R}\KeywordTok{[}\WarningTok{:x}\KeywordTok{]}\NormalTok{)}
1059
+ \ControlFlowTok{end}
1060
+ \end{Highlighting}
1061
+ \end{Shaded}
1062
+
1063
+ Here we create a data frame that has only one column named `x':
1064
+
1065
+ \begin{Shaded}
1066
+ \begin{Highlighting}[]
1067
+ \NormalTok{df1 }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.data\_\_frame}\NormalTok{(}\WarningTok{x:}\NormalTok{ (}\DecValTok{1}\OperatorTok{..}\DecValTok{3}\NormalTok{))}
1068
+ \FunctionTok{puts}\NormalTok{ df1}
1069
+ \end{Highlighting}
1070
+ \end{Shaded}
1071
+
1072
+ \begin{verbatim}
1073
+ ## x
1074
+ ## 1 1
1075
+ ## 2 2
1076
+ ## 3 3
1077
+ \end{verbatim}
1078
+
1079
+ Note that method mutate\_y will fail independetly from the fact that
1080
+ variable `a' is defined and in the scope of the method. Variable `a' has
1081
+ no relationship with the symbol \texttt{R{[}:a{]}} used in the
1082
+ definition of `mutate\_y' above:
1083
+
1084
+ \begin{Shaded}
1085
+ \begin{Highlighting}[]
1086
+ \NormalTok{a }\OperatorTok{=} \DecValTok{10}
1087
+ \ControlFlowTok{begin}
1088
+ \NormalTok{ mutate\_y(df1)}
1089
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
1090
+ \CommentTok{\# Short message only — full backtraces overflow PDF code boxes.}
1091
+ \FunctionTok{puts} \StringTok{"}\SpecialCharTok{\#\{}\NormalTok{e}\AttributeTok{.class}\SpecialCharTok{\}}\StringTok{: }\SpecialCharTok{\#\{}\NormalTok{e}\AttributeTok{.message}\SpecialCharTok{\}}\StringTok{"}
1092
+ \ControlFlowTok{end}
1093
+ \end{Highlighting}
1094
+ \end{Shaded}
1095
+
1096
+ \begin{verbatim}
1097
+ ## NewBridge::SessionClient::RProcessError: Error: i In argument: `y = a + x`.
1098
+ ## Caused by error:
1099
+ ## ! object 'a' not found
1100
+ \end{verbatim}
1101
+
1102
+ \subsection{Different expressions}\label{different-expressions}
1103
+
1104
+ Let's move to the next problem as presented by Hadley where trying to
1105
+ write a function in R that will receive two argumens, the first a
1106
+ variable and the second an expression is not trivial. Below we create a
1107
+ data frame and we want to write a function that groups data by a
1108
+ variable and summarises it by an expression:
1109
+
1110
+ \begin{Shaded}
1111
+ \begin{Highlighting}[]
1112
+ \FunctionTok{set.seed}\NormalTok{(}\DecValTok{123}\NormalTok{)}
1113
+
1114
+ \NormalTok{df }\OtherTok{\textless{}{-}} \FunctionTok{data.frame}\NormalTok{(}
1115
+ \AttributeTok{g1 =} \FunctionTok{c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{2}\NormalTok{),}
1116
+ \AttributeTok{g2 =} \FunctionTok{c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{1}\NormalTok{),}
1117
+ \AttributeTok{a =} \FunctionTok{sample}\NormalTok{(}\DecValTok{5}\NormalTok{),}
1118
+ \AttributeTok{b =} \FunctionTok{sample}\NormalTok{(}\DecValTok{5}\NormalTok{)}
1119
+ \NormalTok{)}
1120
+
1121
+ \FunctionTok{as.data.frame}\NormalTok{(df)}
1122
+ \end{Highlighting}
1123
+ \end{Shaded}
1124
+
1125
+ \begin{verbatim}
1126
+ ## g1 g2 a b
1127
+ ## 1 1 1 3 3
1128
+ ## 2 1 2 2 1
1129
+ ## 3 2 1 5 2
1130
+ ## 4 2 2 4 5
1131
+ ## 5 2 1 1 4
1132
+ \end{verbatim}
1133
+
1134
+ \begin{Shaded}
1135
+ \begin{Highlighting}[]
1136
+ \NormalTok{d2 }\OtherTok{\textless{}{-}}\NormalTok{ df }\SpecialCharTok{\%\textgreater{}\%}
1137
+ \FunctionTok{group\_by}\NormalTok{(g1) }\SpecialCharTok{\%\textgreater{}\%}
1138
+ \FunctionTok{summarise}\NormalTok{(}\AttributeTok{a =} \FunctionTok{mean}\NormalTok{(a))}
1139
+
1140
+ \FunctionTok{as.data.frame}\NormalTok{(d2)}
1141
+ \end{Highlighting}
1142
+ \end{Shaded}
1143
+
1144
+ \begin{verbatim}
1145
+ ## g1 a
1146
+ ## 1 1 2.500000
1147
+ ## 2 2 3.333333
1148
+ \end{verbatim}
1149
+
1150
+ \begin{Shaded}
1151
+ \begin{Highlighting}[]
1152
+ \NormalTok{d2 }\OtherTok{\textless{}{-}}\NormalTok{ df }\SpecialCharTok{\%\textgreater{}\%}
1153
+ \FunctionTok{group\_by}\NormalTok{(g2) }\SpecialCharTok{\%\textgreater{}\%}
1154
+ \FunctionTok{summarise}\NormalTok{(}\AttributeTok{a =} \FunctionTok{mean}\NormalTok{(a))}
1155
+
1156
+ \FunctionTok{as.data.frame}\NormalTok{(d2) }
1157
+ \end{Highlighting}
1158
+ \end{Shaded}
1159
+
1160
+ \begin{verbatim}
1161
+ ## g2 a
1162
+ ## 1 1 3
1163
+ ## 2 2 3
1164
+ \end{verbatim}
1165
+
1166
+ As shown by Hadley, one might expect this function to do the trick:
1167
+
1168
+ \begin{Shaded}
1169
+ \begin{Highlighting}[]
1170
+ \NormalTok{my\_summarise }\OtherTok{\textless{}{-}} \ControlFlowTok{function}\NormalTok{(df, group\_var) \{}
1171
+ \NormalTok{ df }\SpecialCharTok{\%\textgreater{}\%}
1172
+ \FunctionTok{group\_by}\NormalTok{(group\_var) }\SpecialCharTok{\%\textgreater{}\%}
1173
+ \FunctionTok{summarise}\NormalTok{(}\AttributeTok{a =} \FunctionTok{mean}\NormalTok{(a))}
1174
+ \NormalTok{\}}
1175
+
1176
+ \CommentTok{\# my\_summarise(df, g1)}
1177
+ \CommentTok{\#\textgreater{} Error: Column \textasciigrave{}group\_var\textasciigrave{} is unknown}
1178
+ \end{Highlighting}
1179
+ \end{Shaded}
1180
+
1181
+ In order to solve this problem, coding with dplyr requires the
1182
+ introduction of many new concepts and functions such as `quo', `quos',
1183
+ `enquo', `enquos', `!!' (bang bang), `!!!' (triple bang). Again, we'll
1184
+ leave to Hadley the explanation on how to use all those functions.
1185
+
1186
+ Now, let's try to implement the same function in galaaz. The next code
1187
+ block first prints the `df' data frame defined previously in R (to
1188
+ access an R variable from Galaaz, we use the tilde operator
1189
+ `\textasciitilde{}' applied to the R variable name as symbol, i.e.,
1190
+ `:df'. We then create the `my\_summarize' method and call it passing the
1191
+ R data frame and the group by variable `:g1':
1192
+
1193
+ \begin{Shaded}
1194
+ \begin{Highlighting}[]
1195
+ \FunctionTok{puts} \OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}
1196
+ \FunctionTok{print} \StringTok{"}
1197
+ \StringTok{"}
1198
+
1199
+ \ControlFlowTok{def}\NormalTok{ my\_summarize(df, group\_var)}
1200
+ \NormalTok{ df}\AttributeTok{.group\_by}\NormalTok{(group\_var)}\AttributeTok{.}
1201
+ \AttributeTok{summarize}\NormalTok{(}\WarningTok{a:} \ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]}\AttributeTok{.mean}\NormalTok{)}
1202
+ \ControlFlowTok{end}
1203
+
1204
+ \FunctionTok{puts}\NormalTok{ my\_summarize(}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{, }\ConstantTok{R}\KeywordTok{[}\WarningTok{:g1}\KeywordTok{]}\NormalTok{)}
1205
+ \end{Highlighting}
1206
+ \end{Shaded}
1207
+
1208
+ \begin{verbatim}
1209
+ ## g1 g2 a b
1210
+ ## 1 1 1 3 3
1211
+ ## 2 1 2 2 1
1212
+ ## 3 2 1 5 2
1213
+ ## 4 2 2 4 5
1214
+ ## 5 2 1 1 4
1215
+ ##
1216
+ ## # A tibble: 2 x 2
1217
+ ## g1 a
1218
+ ## <dbl> <dbl>
1219
+ ## 1 1 2.5
1220
+ ## 2 2 3.33
1221
+ \end{verbatim}
1222
+
1223
+ It works!!! Well, let's make sure this was not just some coincidence
1224
+
1225
+ \begin{Shaded}
1226
+ \begin{Highlighting}[]
1227
+ \FunctionTok{puts}\NormalTok{ my\_summarize(}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{, }\ConstantTok{R}\KeywordTok{[}\WarningTok{:g2}\KeywordTok{]}\NormalTok{)}
1228
+ \end{Highlighting}
1229
+ \end{Shaded}
1230
+
1231
+ \begin{verbatim}
1232
+ ## # A tibble: 2 x 2
1233
+ ## g2 a
1234
+ ## <dbl> <dbl>
1235
+ ## 1 1 3
1236
+ ## 2 2 3
1237
+ \end{verbatim}
1238
+
1239
+ Great, everything is fine! No magic, no new functions, no complexities,
1240
+ just normal, standard Ruby code. If you've ever done NSE in R, this
1241
+ certainly feels much safer and easy to implement.
1242
+
1243
+ \subsection{Different input variables}\label{different-input-variables}
1244
+
1245
+ In the previous section we've managed to get rid of all NSE formulation
1246
+ for a simple example, but does this remain true for more complex
1247
+ examples, or will the Galaaz way prove inpractical for more complex
1248
+ code?
1249
+
1250
+ In the next example Hadley proposes us to write a function that given an
1251
+ expression such as `a' or `a * b', calculates three summaries. What we
1252
+ want a function that does the same as these R statements:
1253
+
1254
+ \begin{verbatim}
1255
+ summarise(df, mean = mean(a), sum = sum(a), n = n())
1256
+ #> # A tibble: 1 x 3
1257
+ #> mean sum n
1258
+ #> <dbl> <int> <int>
1259
+ #> 1 3 15 5
1260
+
1261
+ summarise(df, mean = mean(a * b), sum = sum(a * b), n = n())
1262
+ #> # A tibble: 1 x 3
1263
+ #> mean sum n
1264
+ #> <dbl> <int> <int>
1265
+ #> 1 9 45 5
1266
+ \end{verbatim}
1267
+
1268
+ Let's try it in galaaz:
1269
+
1270
+ \begin{Shaded}
1271
+ \begin{Highlighting}[]
1272
+ \ControlFlowTok{def}\NormalTok{ my\_summarise2(df, expr)}
1273
+ \NormalTok{ df}\AttributeTok{.summarize}\NormalTok{(}
1274
+ \WarningTok{mean:} \ConstantTok{E}\AttributeTok{.mean}\NormalTok{(expr),}
1275
+ \WarningTok{sum:} \ConstantTok{E}\AttributeTok{.sum}\NormalTok{(expr),}
1276
+ \WarningTok{n:} \ConstantTok{E}\AttributeTok{.n}
1277
+ \NormalTok{ )}
1278
+ \ControlFlowTok{end}
1279
+
1280
+ \FunctionTok{puts}\NormalTok{ my\_summarise2((}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{), }\WarningTok{:a}\NormalTok{)}
1281
+ \FunctionTok{puts}\NormalTok{ my\_summarise2((}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{), }\ConstantTok{R}\KeywordTok{[}\WarningTok{:a}\KeywordTok{]} \OperatorTok{*} \ConstantTok{R}\KeywordTok{[}\WarningTok{:b}\KeywordTok{]}\NormalTok{)}
1282
+ \end{Highlighting}
1283
+ \end{Shaded}
1284
+
1285
+ \begin{verbatim}
1286
+ ## mean sum n
1287
+ ## 1 3 15 5
1288
+ ## mean sum n
1289
+ ## 1 9 45 5
1290
+ \end{verbatim}
1291
+
1292
+ Once again, there is no need to use any special theory or functions. The
1293
+ only point to be careful about is the use of `E' to build expressions
1294
+ from functions `mean', `sum' and `n'.
1295
+
1296
+ \subsection{Different input and output
1297
+ variable}\label{different-input-and-output-variable}
1298
+
1299
+ Now the next challenge presented by Hadley is to vary the name of the
1300
+ output variables based on the received expression. So, if the input
1301
+ expression is `a', we want our data frame columns to be named `mean\_a'
1302
+ and `sum\_a'. Now, if the input expression is `b', columns should be
1303
+ named `mean\_b' and `sum\_b'.
1304
+
1305
+ \begin{verbatim}
1306
+ mutate(df, mean_a = mean(a), sum_a = sum(a))
1307
+ #> # A tibble: 5 x 6
1308
+ #> g1 g2 a b mean_a sum_a
1309
+ #> <dbl> <dbl> <int> <int> <dbl> <int>
1310
+ #> 1 1 1 1 3 3 15
1311
+ #> 2 1 2 4 2 3 15
1312
+ #> 3 2 1 2 1 3 15
1313
+ #> 4 2 2 5 4 3 15
1314
+ #> # … with 1 more row
1315
+
1316
+ mutate(df, mean_b = mean(b), sum_b = sum(b))
1317
+ #> # A tibble: 5 x 6
1318
+ #> g1 g2 a b mean_b sum_b
1319
+ #> <dbl> <dbl> <int> <int> <dbl> <int>
1320
+ #> 1 1 1 1 3 3 15
1321
+ #> 2 1 2 4 2 3 15
1322
+ #> 3 2 1 2 1 3 15
1323
+ #> 4 2 2 5 4 3 15
1324
+ #> # … with 1 more row
1325
+ \end{verbatim}
1326
+
1327
+ In order to solve this problem in R, Hadley needs to introduce some more
1328
+ new functions and notations: `quo\_name' and the `:=' operator from
1329
+ package `rlang'
1330
+
1331
+ Here is our Ruby code:
1332
+
1333
+ \begin{Shaded}
1334
+ \begin{Highlighting}[]
1335
+ \ControlFlowTok{def}\NormalTok{ my\_mutate(df, expr)}
1336
+ \NormalTok{ mean\_name }\OperatorTok{=} \StringTok{"mean\_}\SpecialCharTok{\#\{}\NormalTok{expr}\AttributeTok{.to\_s}\SpecialCharTok{\}}\StringTok{"}
1337
+ \NormalTok{ sum\_name }\OperatorTok{=} \StringTok{"sum\_}\SpecialCharTok{\#\{}\NormalTok{expr}\AttributeTok{.to\_s}\SpecialCharTok{\}}\StringTok{"}
1338
+
1339
+ \NormalTok{ df}\AttributeTok{.mutate}\NormalTok{(mean\_name }\OperatorTok{=\textgreater{}} \ConstantTok{E}\AttributeTok{.mean}\NormalTok{(expr),}
1340
+ \NormalTok{ sum\_name }\OperatorTok{=\textgreater{}} \ConstantTok{E}\AttributeTok{.sum}\NormalTok{(expr))}
1341
+ \ControlFlowTok{end}
1342
+
1343
+ \FunctionTok{puts}\NormalTok{ my\_mutate((}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{), }\WarningTok{:a}\NormalTok{)}
1344
+ \FunctionTok{puts}\NormalTok{ my\_mutate((}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{), }\WarningTok{:b}\NormalTok{)}
1345
+ \end{Highlighting}
1346
+ \end{Shaded}
1347
+
1348
+ \begin{verbatim}
1349
+ ## g1 g2 a b mean_a sum_a
1350
+ ## 1 1 1 3 3 3 15
1351
+ ## 2 1 2 2 1 3 15
1352
+ ## 3 2 1 5 2 3 15
1353
+ ## 4 2 2 4 5 3 15
1354
+ ## 5 2 1 1 4 3 15
1355
+ ## g1 g2 a b mean_b sum_b
1356
+ ## 1 1 1 3 3 3 15
1357
+ ## 2 1 2 2 1 3 15
1358
+ ## 3 2 1 5 2 3 15
1359
+ ## 4 2 2 4 5 3 15
1360
+ ## 5 2 1 1 4 3 15
1361
+ \end{verbatim}
1362
+
1363
+ It really seems that ``Non Standard Evaluation'' is actually quite
1364
+ standard in Galaaz! But, you might have noticed a small change in the
1365
+ way the arguments to the mutate method were called. In a previous
1366
+ example we used df.summarise(mean: E.mean(:a), \ldots) where the column
1367
+ name was followed by a `:' colom. In this example, we have
1368
+ df.mutate(mean\_name =\textgreater{} E.mean(expr), \ldots) and variable
1369
+ mean\_name is not followed by `:' but by `=\textgreater{}'. This is
1370
+ standard Ruby notation.
1371
+
1372
+ {[}explain\ldots.{]}
1373
+
1374
+ \subsection{Capturing multiple
1375
+ variables}\label{capturing-multiple-variables}
1376
+
1377
+ Moving on with new complexities, Hadley proposes us to solve the problem
1378
+ in which the summarise function will receive any number of grouping
1379
+ variables.
1380
+
1381
+ This again is quite standard Ruby. In order to receive an undefined
1382
+ number of paramenters the paramenter is preceded by '*':
1383
+
1384
+ \begin{Shaded}
1385
+ \begin{Highlighting}[]
1386
+ \ControlFlowTok{def}\NormalTok{ my\_summarise3(df, }\OperatorTok{*}\NormalTok{group\_vars)}
1387
+ \NormalTok{ df}\AttributeTok{.group\_by}\NormalTok{(}\OperatorTok{*}\NormalTok{group\_vars)}\AttributeTok{.}
1388
+ \AttributeTok{summarise}\NormalTok{(}\WarningTok{a:} \ConstantTok{E}\AttributeTok{.mean}\NormalTok{(}\WarningTok{:a}\NormalTok{))}
1389
+ \ControlFlowTok{end}
1390
+
1391
+ \FunctionTok{puts}\NormalTok{ my\_summarise3((}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:df}\KeywordTok{]}\NormalTok{), }\WarningTok{:g1}\NormalTok{, }\WarningTok{:g2}\NormalTok{)}
1392
+ \end{Highlighting}
1393
+ \end{Shaded}
1394
+
1395
+ \begin{verbatim}
1396
+ ## # A tibble: 4 x 3
1397
+ ## # Groups: g1 [2]
1398
+ ## g1 g2 a
1399
+ ## <dbl> <dbl> <dbl>
1400
+ ## 1 1 1 3
1401
+ ## 2 1 2 2
1402
+ ## 3 2 1 3
1403
+ ## 4 2 2 4
1404
+ \end{verbatim}
1405
+
1406
+ \section{Why does R require NSE and Galaaz does
1407
+ not?}\label{why-does-r-require-nse-and-galaaz-does-not}
1408
+
1409
+ NSE introduces a number of new concepts, such as `quoting',
1410
+ `quasiquotation', `unquoting' and `unquote-splicing', while in Galaaz
1411
+ none of those concepts are needed. What gives?
1412
+
1413
+ R is an extremely flexible language and it has lazy evaluation of
1414
+ parameters. When in R a function is called as `summarise(df, a = b)',
1415
+ the summarise function receives the litteral `a = b' parameter and can
1416
+ work with this as if it were a string. In R, it is not clear what a and
1417
+ b are, they can be expressions or they can be variables, it is up to the
1418
+ function to decide what `a = b' means.
1419
+
1420
+ In Ruby, there is no lazy evaluation of parameters and `a' is always a
1421
+ variable and so is `b'. Variables assume their value as soon as they are
1422
+ used, so `x = a' is immediately evaluate and variable `x' will receive
1423
+ the value of variable `a' as soon as the Ruby statement is executed.
1424
+ Ruby also provides the notion of a symbol; `:a' is a symbol and does not
1425
+ evaluate to anything. Galaaz uses Ruby symbols to build expressions that
1426
+ are not bound to anything: `R{[}:a{]}.eq R{[}:b{]}' is clearly an
1427
+ expression and has no relationship whatsoever with the statment `a = b'.
1428
+ By using symbols, variables and expressions all the possible ambiguities
1429
+ that are found in R are eliminated in Galaaz.
1430
+
1431
+ The main problem that remains, is that in R, functions are not clearly
1432
+ documented as what type of input they are expecting, they might be
1433
+ expecting regular variables or they might be expecting expressions and
1434
+ the R function will know how to deal with an input of the form `a = b',
1435
+ now for the Ruby developer it might not be immediately clear if it
1436
+ should call the function passing the value `true' if variable `a' is
1437
+ equal to variable `b' or if it should call the function passing the
1438
+ expression `R{[}:a{]}.eq R{[}:b{]}'.
1439
+
1440
+ \section{Advanced dplyr features}\label{advanced-dplyr-features}
1441
+
1442
+ In the blog:
1443
+ \href{https://www.r-bloggers.com/programming-with-dplyr-by-using-dplyr/}{Programming
1444
+ with dplyr by using dplyr} Iñaki Úcar shows surprise that some R users
1445
+ are trying to code in dplyr avoiding the use of NSE. For instance he
1446
+ says:
1447
+
1448
+ \begin{quote}
1449
+ Take the example of seplyr. It stands for standard evaluation dplyr, and
1450
+ enables us to program over dplyr without having ``to bring in (or study)
1451
+ any deep-theory or heavy-weight tools such as rlang/tidyeval''.
1452
+ \end{quote}
1453
+
1454
+ For me, there isn't really any surprise that users are trying to avoid
1455
+ dplyr deep-theory. R users frequently are not programmers and learning
1456
+ to code is already hard business, on top of that, having to learn how to
1457
+ `quote' or `enquo' or `quos' or `enquos' is not necessarily a `piece of
1458
+ cake'. So much so, that `tidyeval' has some more advanced functions that
1459
+ instead of using quoted expressions, uses strings as arguments.
1460
+
1461
+ In the following examples, we show the use of functions `group\_by\_at',
1462
+ `summarise\_at' and `rename\_at' that receive strings as argument. The
1463
+ data frame used in `starwars' that describes features of characters in
1464
+ the Starwars movies:
1465
+
1466
+ \begin{Shaded}
1467
+ \begin{Highlighting}[]
1468
+ \FunctionTok{puts}\NormalTok{ (}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:starwars}\KeywordTok{]}\NormalTok{)}\AttributeTok{.head}
1469
+ \end{Highlighting}
1470
+ \end{Shaded}
1471
+
1472
+ \begin{verbatim}
1473
+ ## # A tibble: 6 x 14
1474
+ ## name height mass hair_color skin_color eye_color birth_year sex
1475
+ ## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr>
1476
+ ## 1 Luke ~ 172 77 blond fair blue 19 male
1477
+ ## 2 C-3PO 167 75 <NA> gold yellow 112 none
1478
+ ## 3 R2-D2 96 32 <NA> white, bl~ red 33 none
1479
+ ## 4 Darth~ 202 136 none white yellow 41.9 male
1480
+ ## 5 Leia ~ 150 49 brown light brown 19 fema~
1481
+ ## 6 Owen ~ 178 120 brown, gr~ light blue 52 male
1482
+ ## # i 6 more variables: gender <chr>, homeworld <chr>, species <chr>,
1483
+ ## # films <list>, vehicles <list>, starships <list>
1484
+ \end{verbatim}
1485
+
1486
+ The grouped\_mean function below will receive a grouping variable and
1487
+ calculate summaries for the value\_variables given:
1488
+
1489
+ \begin{Shaded}
1490
+ \begin{Highlighting}[]
1491
+ \NormalTok{grouped\_mean }\OtherTok{\textless{}{-}} \ControlFlowTok{function}\NormalTok{(data, grouping\_variables, value\_variables) \{}
1492
+ \NormalTok{ data }\SpecialCharTok{\%\textgreater{}\%}
1493
+ \FunctionTok{group\_by\_at}\NormalTok{(grouping\_variables) }\SpecialCharTok{\%\textgreater{}\%}
1494
+ \FunctionTok{mutate}\NormalTok{(}\AttributeTok{count =} \FunctionTok{n}\NormalTok{()) }\SpecialCharTok{\%\textgreater{}\%}
1495
+ \FunctionTok{summarise\_at}\NormalTok{(}\FunctionTok{c}\NormalTok{(value\_variables, }\StringTok{"count"}\NormalTok{), mean, }\AttributeTok{na.rm =} \ConstantTok{TRUE}\NormalTok{) }\SpecialCharTok{\%\textgreater{}\%}
1496
+ \FunctionTok{rename\_at}\NormalTok{(value\_variables, }\FunctionTok{funs}\NormalTok{(}\FunctionTok{paste0}\NormalTok{(}\StringTok{"mean\_"}\NormalTok{, .)))}
1497
+ \NormalTok{ \}}
1498
+
1499
+ \NormalTok{gm }\OtherTok{=}\NormalTok{ starwars }\SpecialCharTok{\%\textgreater{}\%}
1500
+ \FunctionTok{grouped\_mean}\NormalTok{(}\StringTok{"eye\_color"}\NormalTok{, }\FunctionTok{c}\NormalTok{(}\StringTok{"mass"}\NormalTok{, }\StringTok{"birth\_year"}\NormalTok{))}
1501
+ \end{Highlighting}
1502
+ \end{Shaded}
1503
+
1504
+ \begin{verbatim}
1505
+ ## Warning: `funs()` was deprecated in dplyr 0.8.0.
1506
+ ## i Please use a list of either functions or lambdas:
1507
+ ##
1508
+ ## # Simple named list: list(mean = mean, median = median)
1509
+ ##
1510
+ ## # Auto named with `tibble::lst()`: tibble::lst(mean, median)
1511
+ ##
1512
+ ## # Using lambdas list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
1513
+ ## Call `lifecycle::last_lifecycle_warnings()` to see where this warning
1514
+ ## was generated.
1515
+ \end{verbatim}
1516
+
1517
+ \begin{Shaded}
1518
+ \begin{Highlighting}[]
1519
+ \FunctionTok{as.data.frame}\NormalTok{(gm) }
1520
+ \end{Highlighting}
1521
+ \end{Shaded}
1522
+
1523
+ \begin{verbatim}
1524
+ ## eye_color mean_mass mean_birth_year count
1525
+ ## 1 black 76.28571 33.00000 10
1526
+ ## 2 blue 86.51667 67.06923 19
1527
+ ## 3 blue-gray 77.00000 57.00000 1
1528
+ ## 4 brown 66.09231 108.96429 21
1529
+ ## 5 dark NaN NaN 1
1530
+ ## 6 gold NaN NaN 1
1531
+ ## 7 green, yellow 159.00000 NaN 1
1532
+ ## 8 hazel 66.00000 34.50000 3
1533
+ ## 9 orange 282.33333 231.00000 8
1534
+ ## 10 pink NaN NaN 1
1535
+ ## 11 red 81.40000 33.66667 5
1536
+ ## 12 red, blue NaN NaN 1
1537
+ ## 13 unknown 31.50000 NaN 3
1538
+ ## 14 white 48.00000 NaN 1
1539
+ ## 15 yellow 81.11111 76.38000 11
1540
+ \end{verbatim}
1541
+
1542
+ The same code with Galaaz, becomes:
1543
+
1544
+ \begin{Shaded}
1545
+ \begin{Highlighting}[]
1546
+ \ControlFlowTok{def}\NormalTok{ grouped\_mean(data, grouping\_variables, value\_variables)}
1547
+ \NormalTok{ data}\AttributeTok{.}
1548
+ \AttributeTok{group\_by\_at}\NormalTok{(grouping\_variables)}\AttributeTok{.}
1549
+ \AttributeTok{mutate}\NormalTok{(}\WarningTok{count:} \ConstantTok{E}\AttributeTok{.n}\NormalTok{)}\AttributeTok{.}
1550
+ \AttributeTok{summarise\_at}\NormalTok{(}
1551
+ \ConstantTok{E}\AttributeTok{.c}\NormalTok{(value\_variables, }\StringTok{"count"}\NormalTok{),}
1552
+ \ConstantTok{R}\KeywordTok{[}\WarningTok{:mean}\KeywordTok{]}\NormalTok{,}
1553
+ \WarningTok{na\_\_rm:} \DecValTok{true}\NormalTok{)}\AttributeTok{.}
1554
+ \AttributeTok{rename\_at}\NormalTok{(}
1555
+ \NormalTok{ value\_variables,}
1556
+ \ConstantTok{E}\AttributeTok{.funs}\NormalTok{(}\ConstantTok{E}\AttributeTok{.paste0}\NormalTok{(}\StringTok{"mean\_"}\NormalTok{, value\_variables)))}
1557
+ \ControlFlowTok{end}
1558
+
1559
+ \FunctionTok{puts}\NormalTok{ grouped\_mean(}
1560
+ \NormalTok{ (}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:starwars}\KeywordTok{]}\NormalTok{),}
1561
+ \StringTok{"eye\_color"}\NormalTok{,}
1562
+ \ConstantTok{E}\AttributeTok{.c}\NormalTok{(}\StringTok{"mass"}\NormalTok{, }\StringTok{"birth\_year"}\NormalTok{))}
1563
+ \end{Highlighting}
1564
+ \end{Shaded}
1565
+
1566
+ \begin{verbatim}
1567
+ ## # A tibble: 15 x 4
1568
+ ## eye_color mean_mass mean_birth_year count
1569
+ ## <chr> <dbl> <dbl> <dbl>
1570
+ ## 1 black 76.3 33 10
1571
+ ## 2 blue 86.5 67.1 19
1572
+ ## 3 blue-gray 77 57 1
1573
+ ## 4 brown 66.1 109. 21
1574
+ ## 5 dark NaN NaN 1
1575
+ ## 6 gold NaN NaN 1
1576
+ ## 7 green, yellow 159 NaN 1
1577
+ ## 8 hazel 66 34.5 3
1578
+ ## 9 orange 282. 231 8
1579
+ ## 10 pink NaN NaN 1
1580
+ ## 11 red 81.4 33.7 5
1581
+ ## 12 red, blue NaN NaN 1
1582
+ ## 13 unknown 31.5 NaN 3
1583
+ ## 14 white 48 NaN 1
1584
+ ## 15 yellow 81.1 76.4 11
1585
+ \end{verbatim}
1586
+
1587
+ \section{Further reading}\label{further-reading}
1588
+
1589
+ \begin{itemize}
1590
+ \tightlist
1591
+ \item
1592
+ \href{https://www.jruby.org/}{JRuby} --- Ruby on the JVM (Galaaz 2.0)
1593
+ \item
1594
+ \href{https://medium.freecodecamp.org/how-to-make-beautiful-ruby-plots-with-galaaz-320848058857}{How
1595
+ to make Beautiful Ruby Plots with Galaaz} (plots; narrative partly
1596
+ pre-2.0)
1597
+ \item
1598
+ \href{https://towardsdatascience.com/ruby-plotting-with-galaaz-an-example-of-tightly-coupling-ruby-and-r-in-graalvm-520b69e21021}{Ruby
1599
+ Plotting with Galaaz in GraalVM} (older stack; ideas still useful)
1600
+ \item
1601
+ \href{https://towardsdatascience.com/how-to-do-reproducible-research-in-ruby-with-gknit-c26d2684d64e}{How
1602
+ to do reproducible research in Ruby with gKnit}
1603
+ \item
1604
+ \href{https://r4ds.had.co.nz/}{R for Data Science}
1605
+ \item
1606
+ \href{https://adv-r.hadley.nz/}{Advanced R}
1607
+ \item
1608
+ Historical context: \href{https://www.graalvm.org/}{GraalVM},
1609
+ \href{https://github.com/oracle/truffleruby}{TruffleRuby},
1610
+ \href{https://github.com/oracle/fastr}{FastR}
1611
+ \end{itemize}
1612
+
1613
+ \section{Conclusion}\label{conclusion}
1614
+
1615
+ Ruby and Galaaz provide a nice framework for developing code that uses R
1616
+ functions. Although R is a very powerful and flexible language,
1617
+ sometimes, too much flexibility makes life harder for the casual user.
1618
+ We believe however, that even for the advanced user, Ruby integrated
1619
+ with R throught Galaaz, makes a powerful environment for data analysis.
1620
+ In this blog post we showed how Galaaz consistent syntax eliminates the
1621
+ need for complex constructs such as quoting, enquoting, quasiquotation,
1622
+ etc. This simplification comes from the fact that expressions and
1623
+ variables are clearly separated objects, which is not the case in the R
1624
+ language.
1625
+
1626
+ \end{document}