I have a rmd document where I have the following
```{r code_block, echo=FALSE}
A = matrix(c(1,3,0,1),2,2)
B = matrix(c(5,3,1,4),2,2)
```
$$
\\begin{bmatrix}
1
This is a perfect use case for knitr::knit_print()
.
You will find details about the knitr::knit_print()
method in its dedicated vignette:
vignette('knit_print', package = 'knitr')
The goal is to provide a knit_print
method for objects of class matrix
. As other answers suggested, it could be useful to define operators.
You will find below an Rmd
file that provides a solution to your problem. It also contains a proposal for operators.
The main feature of this answer is that you only have to write
`r A`
to output the matrix A in LaTeX inline mode (no $
to type) and write
```{r echo=FALSE}
A
```
to write in LaTeX display mode.
I also propose you to define a %times%
operator. Therefore, you only have to write:
`r A %times% B`
This answer is quite generic and you should be able to extend it to other objects.
---
title: "R Markdown: Display a Matrix for R Variable"
author: "Romain Lesur"
output:
html_document:
keep_md: true
---
```{r setup, include=FALSE}
# Define a generic method that transforms an object x in a LaTeX string
as_latex = function(x, ...) {
UseMethod('as_latex', x)
}
# Define a class latex for LaTeX expressions
as_latex.character = function(x) {
structure(
paste(x, collapse = ' '),
class = c('latex', 'character')
)
}
# A character string of class latex is rendered in display mode
# Define a knit_print() method for the latex class
knit_print.latex = function(x, ...) {
knitr::asis_output(
paste0('$$', x, '$$')
)
}
# Now, define a method as_latex for matrix
as_latex.matrix = function(x, ...) {
as_latex(c(
'\\begin{bmatrix}',
paste(
t(x),
rep(c(rep('&', nrow(x) - 1), '\\\\'), ncol(x)),
collapse = ''
),
'\\end{bmatrix}'
))
}
# Indicate to knitr that matrix are rendered as latex
knit_print.matrix = function(x, ...) {
knitr::knit_print(as_latex(x))
}
# Build a knitr inline hook to display inline latex in inline mode
default_inline_hook = knitr::knit_hooks$get('inline')
knitr::knit_hooks$set(inline = function(x) {
x = paste(gsub('\\$\\$', '$', x))
default_inline_hook(x)
})
```
```{r}
A = matrix(c(1,3,0,1),2,2)
B = matrix(c(5,3,1,4),2,2)
```
Now, matrix are rendered as LaTeX:
Matrix A in inline mode: `r A`
Matrix A in display mode:
```{r echo=FALSE}
A
```
### Operators
As other answers suggested, it could be useful to define operators.
With the previous class, it is relatively straightforward:
```{r operators, include=FALSE}
`%times%` = function(x, y) {
as_latex(sapply(list(x, '\\times', y), as_latex))
}
`%add%` = function(x, y) {
as_latex(sapply(list(x, '+', y), as_latex))
}
```
Example in inline mode: `r A %add% A %times% B`
Display mode:
```{r echo=FALSE}
A %times% B
```
I figured out a function that plugs the numbers from the matrix into the correct LaTeX code. In the code block where you use it you need results='asis'
to get the LaTeX to render, and you can wrap the function in writeLines
along with the other parts you need.
I'm still open to more elegant solutions.
```{r}
A <- matrix(c(1, 3, 0, 1), 2, 2)
B <- matrix(c(5, 3, 1, 4), 2, 2)
# Utility function to print matrices in proper LaTeX format
print_mat <- function(mat) {
n <- nrow(mat)
c('\\begin{bmatrix}',
paste0(sapply(seq_len(n - 1),
function(i) paste0(mat[i, ], collapse = ' & ')),
' \\\\'),
paste0(mat[n, ], collapse = ' & '),
'\\end{bmatrix}')
}
```
```{r, results = 'asis'}
writeLines(c('$$',
print_mat(A),
'\\times',
print_mat(B),
'$$'))
```
Straightforwardly, you can write latex line. writeLines()
or cat()
would be helpful.
You can use apply(A, 1)
with two step paste()
.
paste(collpase = "&")
: collapse each rowpaste(, "\\\\")
: collapse every column with \\
Then we can get the latex
formula of matrix.
write_matex <- function(x) {
begin <- "$$\\begin{bmatrix}"
end <- "\\end{bmatrix}$$"
X <-
apply(x, 1, function(x) {
paste(
paste(x, collapse = "&"),
"\\\\"
)
})
writeLines(c(begin, X, end))
}
If you conduct this function, write_matex(A)
gives
$$\begin{bmatrix}
1&0 \\
3&1 \\
\end{bmatrix}$$
When you use chunk option {r, results = 'asis'}
, you might see the matrix in both pdf and html.
Based on this function, you might freely use matrix in latex block. For this, $$
should be removed in the function. Instead of writeLines()
, paste(collapse = "")
can be used.
write_matex2 <- function(x) {
begin <- "\\begin{bmatrix}"
end <- "\\end{bmatrix}"
X <-
apply(x, 1, function(x) {
paste(
paste(x, collapse = "&"),
"\\\\"
)
})
paste(c(begin, X, end), collapse = "")
}
In the text part, you can implement this function as
$$
`r write_matex2(A)` \times `r write_matex2(B)`
$$
In r markdown
, this r
with back quotation can attach your r function and variable. So you can get
As you can see, this is reproducible.
(C <- matrix(1:10, nrow = 2))
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 3 5 7 9
#> [2,] 2 4 6 8 10
Similarly,
$$`r write_matex2(C)` + `r write_matex2(C)`$$
hello you can use library(printr)
in a markdown block
knitr::kable(A , caption = "matrix A")
from https://yihui.name/printr/
like this
```{r code_block, echo=FALSE}
A = matrix(c(1,3,0,1),2,2)
B = matrix(c(5,3,1,4),2,2)
knitr::kable(A , caption = "matrix A")
```