Knitr: R code within LaTeX environment in a Markdo

2019-03-11 07:59发布

问题:

I have a document in Markdown, which incorporates R code via Knitr. For rendering equations I use LaTeX, simply writing its commands in the text. Say I have the following LaTeX code:

\begin{displaymath}
\mathbf{X} = \begin{bmatrix}
2 & 12\\ 
3 & 17\\ 
5 & 10\\ 
7 & 18\\ 
9 & 13\\
\end{bmatrix}
\end{displaymath}

Which renders me a nice mathematical matrix representation (in square brackets), when I convert everything to PDF (the full workflow is then: RMD -> knitr -> MD -> pandoc -> TeX -> pandoc -> PDF).

Now, suppose we want the said matrix to be generated on-the-fly from an R object, some R matrix x. In this post we establish how to generate the required LaTeX code (the matrix2latex() function is defined there). The question now is how to get Knitr to evaluate it. I tried the following code:

\begin{displaymath}
\mathbf{X} = `r matrix2latex(x)`
\end{displaymath} 

but it simply produces blank space (NULL actually) where the R output should be. I am surprised this hasn't been asked already (at least my own search yielded nothing). Any ideas how to make this work?

EDIT:

As suggested, rewrote the function without cat(). Here is the working version of the function for future reference:

m2l <- function(matr) {

    printmrow <- function(x) {

        ret <- paste(paste(x,collapse = " & "),"\\\\")
        sprintf(ret)
    }

    out <- apply(matr,1,printmrow)
    out2 <- paste("\\begin{bmatrix}",paste(out,collapse=' '),"\\end{bmatrix}")
    return(out2)
}

回答1:

This is because your matrix2latex function uses cat and sends its output to the standard output stream, which isn't where knitr is trying to put the output.

Two solutions: one is to rewrite your function to construct the output as a string using paste and sprintf or other string formatting functions, or as a quick hack just wrap it in capture.output thus:

m2l = function(matr){capture.output(matrix2latex(matr))}

Then in your .Rmd file:

\begin{displaymath}
\mathbf{X} = `r m2l(x)`
\end{displaymath}

becomes

\mathbf{X} = \begin{bmatrix} , 0.06099 & 0.768 \\ , 0.6112 & 0.004696 \\ , 0.02729 & 0.6198 \\ , 0.8498 & 0.3308 \\ , 0.6869 & 0.103 \\ , \end{bmatrix}

which although isn't quite perfect does illustrate the principle. The code inserted by the inline expression is the value of it, not what it prints or cats.