How to get \bm{} to work in an R markdown (to HTML

2020-06-03 05:36发布

My R Markdown (.Rmd) file looks like this:

---
title: Foo
author: Marius Hofert
header-includes:
    - \usepackage{bm}
output:
    pdf_document
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{Foo}
---
\[
\begin{align}
   \bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\end{align}
\]

The output (obtained via R CMD build and the looking in ./inst/doc/*.html) is this:

enter image description here

For getting italics bold vectors, I would like to use \bm{X} in my .Rmd document, but it fails (although I load the package bm). Why? The same happens without the output: pdf_document part.

UPDATE

If I'm running

---
title: Foo
author: Marius Hofert
header-includes:
    - \usepackage{bm}
output:
    pdf_document
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{Foo}
---
\[
\begin{align}
   \bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\end{align}
\]

\[
   \bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\]

\begin{align}
   \bm{U}=a\bm{X}\quad\boldmath{U}=a\boldmath{X}\quad\mathbf{U}=a\mathbf{X}.
\end{align}

I get (without errors)

this

标签: r latex markdown
4条回答
叛逆
2楼-- · 2020-06-03 05:49

I don't think Mathjax (which is what Pandoc uses in HTML output) can \usepackage{}. I work around this by having 2 files: one called preamble-mathjax.tex, one called preamble-latex.texMy YAML metadata is set up like this (for rmarkdown):

output:
    html_document:
       includes:
         before_body: preamble-mathjax.tex
    pdf_document:
       includes:
         in_header: preamble-latex.tex

And preamble-mathjax.tex has (note surrounding \( \) so that mathjax parses as a maths block)

\(
\newcommand{\bm}[1]{\boldsymbol{\mathbf{#1}}}
\)

while preamble-latex.tex has:

\usepackage{bm}

So that whenever I use \bm{..} in my document, it works whether I compile to HTML or PDF. (stacking the boldsymbol with the mathbf so that both greek letters and normal letters are made bold, and bold letters remain upright as they would if you used \bm).


Peripheral to your question: Eventually you may wish to have a third file, preamble-both.tex, with macros that are not package-specific (supposing the relevant preamble-* has already been included) e.g.

\newcommand{\bX}{\bm{X}} % bold X
\newcommand{\R}{\mathbb{R}} % real numbers

And then you include this with both output formats. This saves you from writing all your macros twice, once for html_document and again for pdf_document. However, MathJax requires the macros to be surrounded by \( and \), whereas LaTeX will error out if this is the case.

The only way I've found to work around this is to have a file bracket-start.txt containing just \( and a file bracket-end.txt containing just \), so that my YAML is:

output:
    html_document:
       includes:
         before_body: [preamble-mathjax.tex, bracket-start.txt, preamble-both.tex, bracket-end.txt]
    pdf_document:
       includes:
         in_header: preamble-latex.tex
         before_body: preamble-both.tex

which is pretty unwieldy, but it works (there is the Pandoc latex_macros extension, but it has never worked for me)

查看更多
▲ chillily
3楼-- · 2020-06-03 05:59

A third solution works well if you are using Mathjax to render equations in your html docs. Mathjax is on by default in pandoc in RStudio. This has the advantage of no flickering and works in $$ $$ and the equation environment. The big downside to this is that pandoc strips \ref{} out of the html so you have to add a knit hook to change to \ref{}. Surely there is a way to tell pandoc not to do this, but I couldn't find it. I tried many different pandoc args with no success.

This example assumes you want equation numbers and you want to crossref those in your text. It also assumes you are knitting from RStudio. Probably works otherwise, but that is what I tested in.

mathjax.js --- define the macros here and tell Mathjax to add eqn #s

<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script type="text/x-mathjax-config"> 
  MathJax.Hub.Config({ 
    TeX: { 
      equationNumbers: {autoNumber: "all"},
      Macros: {
        AA: "{\\bf A}",
        BB: "{\\bf B}"
      }
    } 
  });
</script>

defs.tex --- this is for pdf_document

\def\AA{\bf A}
\def\BB{\bf B}

test.Rmd --- now we can make Rmd docs that work with html and pdf. I could not figure out how to tell pandoc not to strip LaTeX commands out of the html. So passed in a knit hook to double \ the \ref{} calls.

---
title: "Test"
knit: ( function(inputFile, encoding) { if(rmarkdown::all_output_formats(inputFile)[1]=="html_document"){ f <- inputFile; x <- readLines(f); y <- gsub("[\\]ref[{]","\\\\\\\\ref{", x); cat(y,file="tmp.Rmd", sep="\n"); rmarkdown::render("tmp.Rmd", encoding = encoding ) }else{ rmarkdown::render(inputFile, encoding = encoding ) } })
output: 
  html_document:
    includes:
      before_body: [../tex/mathjax.html]
  pdf_document: 
    includes: 
      before_body: ../tex/defs2.tex
---

```{r mss-setup, include=FALSE, purl=FALSE}
knitr::opts_knit$set(unnamed.chunk.label = "tvarss-")
```

In the pdf, this will not have a number but in the html it will.

$$
\AA^\top\BB
$$
You can use nonumber if you need the equation numbering to be the same in html and pdf.

$$
\AA^\top\BB\nonumber
$$

If we want to crossref an equation, use equation environment.  
\begin{equation}
\AA^\top\BB
\label{eqn1}\end{equation}
This is Equation \ref{eqn1}.

Here is the knit function:

( function(inputFile, encoding) { if(rmarkdown::all_output_formats(inputFile)[1]=="html_document"){ f <- inputFile; x <- readLines(f); y <- gsub("[\]ref[{]","\\\\ref{", x); cat(y,file="tmp.Rmd", sep="\n"); rmarkdown::render("tmp.Rmd", encoding = encoding ) }else{ rmarkdown::render(inputFile, encoding = encoding ) } })

查看更多
够拽才男人
4楼-- · 2020-06-03 06:02

I think your \[ \] and \begin{align} ... \end{align} are redundant. When I ran it as written above I got

! Package amsmath Error: Erroneous nesting of equation structures; (amsmath) trying to recover with `aligned'.

See the amsmath package documentation for explanation. Type H for immediate help. ...

l.84 \end{align}

Worked fine for me when I deleted \begin{align} ... \end{align} ...

(It seems that a similar issue arose in your previous question too ...)

(Perhaps you were getting errors that you didn't notice and were accidentally looking at a previously compiled version?)


As far as why you don't get the right HTML output: I'm pretty certain that MathJax (the engine used to render LaTeX embedded in Rmarkdown-produced HTML) doesn't know about \boldmath; adding the package to your LaTeX input won't help, you'll have to use \mathbf and \boldsymbol instead. You can play around here to see what works and what doesn't: entering

$\bm X \boldmath X \boldsymbol X \mathbf X$

at that web page gives

enter image description here

Bottom line, if you want fancy math rendered properly, you're probably better off sticking to PDF output.

查看更多
劳资没心,怎么记你
5楼-- · 2020-06-03 06:04

Another solution is to use the child chunk argument. The downside, which is kind of major, is that it will only work for math surrounded by $ $ or $$ $$. It won't work in the equation environment. The upside is that you do not get your definitions "flashing" at the top of your html pages for a moment, which happens to me with the solution above.

demo.Rmd

---
title: Foo
output:
  pdf_document: default
  html_document: default
---

```{r child = 'defs.tex'}
```

My math definitions are in defs.tex.  Now I can use the defs in equations
but they need to be in math mode for html output.  This works for both
pdf and html:
$\AA^\top\BB$ and 
$$\AA^\top\BB$$

But using your new commands in the equation environment
only works for pdf output because pandoc will not expand the
definitions if the newcommands are not in $ $ or $$ $$.    

\begin{equation}
\AA^\top\BB
\end{equation}

defs.tex

\newcommand{\BB}{\mathbf{B}}
\newcommand{\CC}{\mathbf{C}}
\renewcommand{\AA}{\mathbf{A}}
查看更多
登录 后发表回答