Technical reports written in RMarkdown usually include mathematical symbols. RMarkdown addresses that by supporting the inclussion of raw LaTeX code. Depending on the desired output format, the code gets rendered by some LaTeX engine. This feature is very convenient.
The issue here is that writing LaTeX code can be cumbersome and the
result is usually hard to read. Although the use of
newcommand can alleviate that, in practice people use it
infrequently. The idea behind this package is that if you’re writing an
RMarkdown report, you’re already using R, so yuo might as well use it to
write your LaTeX code as well.
This is best explained through an example. Consider the following equation, encountered in Riemannian geometry:
\[ \frac{d}{dt} \langle V,W \rangle = \langle \frac{DV}{dt}, W \rangle + \langle V, \frac{DW}{dt} \rangle \]
The straightforward way to code that is:
\frac{d}{dt} \langle V,W \rangle = \langle \frac{DV}{dt}, W \rangle + \langle V, \frac{DW}{dt} \rangleIf you were to use latexSymb, you would proceed as
follows instead. First you would create objects of class
latex_symb to represent the vector fields:
## Loading required package: purrr
##
## Attaching package: 'latexSymb'
## The following objects are masked from 'package:base':
##
## *, +, -, /, ^
Then you would write R functions to represent the mathematical concepts being used: the inner product, the covariant derivative and the ordinary derivative:
inner <- function(x,y) ang(lsymb(x, ",", y))
cov.der <- function(x) lsymb("D", x)/"dt"
ddt <- function(x) lsymb("d", x)/"dt"Then you would put everything in an equation
environment:
lenv("equation",
lsymb(
ddt(inner(vf1, vf2)),
"=",
inner(cov.der(vf1), vf2) + inner(vf1, cov.der(vf2))
)
)## [1] "\\begin{equation}\\n\\frac{ d \\langle V , W \\rangle }{ dt } = \\langle \\frac{ D V }{ dt } , W \\rangle + \\langle V , \\frac{ D W }{ dt } \\rangle\\n\\end{equation}"
A caveat here is that your chuncks should have the options
results='asis', include=FALSE so that you obtain the plain
LaTeX code.
Let us unpack all of this.
Notice first that in the definition of cov.der an
important feature is being used. Namely, the / function is
overwritten by latexSymb so that if either of its arguments
are objects of class latex_symb, the output is another
object of that class that uses frac as you would expect.
This is also done with +, -, *
and ^. Additionally, under adds support for
the use of subscripts.
Also, in the numerator of cov.der,
lsymb("D", x) concatenates the string "D" and
the object x, and wraps the result in a new
latex_symb object.
Further, there’s the use of the latexSymb function
ang, which provides the dynamic enclosing for the inner
product, thus avoiding the need to write left and
right. The functions br, sqbr and
pths do the same for braces, square brackets and
parentheses respectively.
Finally, there is the function lenv that spares the user
from writing begin and end. The second
argument is a list or a vector, whose components represent different
lines. So, for instance, we could have written also
lenv("align*",
c(
lsymb(ddt(inner(vf1, vf2)), "&=\\\\"),
lsymb("&=", inner(cov.der(vf1), vf2) + inner(vf1, cov.der(vf2)))
)
)## [1] "\\begin{align*}\\n\\frac{ d \\langle V , W \\rangle }{ dt } &=\\\\\\n&= \\langle \\frac{ D V }{ dt } , W \\rangle + \\langle V , \\frac{ D W }{ dt } \\rangle\\n\\end{align*}"
latex_symb also exposes il, which surrounds
expressions in dollar signs, for inline math environments.
On the whole, latexSymb may not significantly reduce the
amount of code users have to write compared to raw LaTeX. But I do think
it makes it more readable and hence less prone to errors. Users can
mostly write what they mean, not what they want to see.
Additionally, latexSymb is not limited to RMarkdown.
Actually, it probably makes more sense in .Rtex documents.
In any case, any format that knit can handle will do.
Finally, for very complicated equations, R’s piping should make things even more readable.