For R Markdown, How do I display a matrix from R variable

喜夏-厌秋 提交于 2020-05-25 06:54:25

问题


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  & 0 \\ 
3 & 1 \\ 
\end{bmatrix}
*
\begin{bmatrix} 
5 & 1 \\ 
3 & 4 \\ 
\end{bmatrix}
$$

Now I would like to instead of hard coding the LaTeX part manually, I could use the matrix from the variables A and B instead. How could this be done?

Thanks.


回答1:


Straightforwardly, you can write latex line. writeLines() or cat() would be helpful.

You can use apply(A, 1) with two step paste().

  1. paste(collpase = "&"): collapse each row
  2. paste(, "\\\\"): 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.


Latex block

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)`$$




回答2:


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
```



回答3:


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),
             '$$'))
```




回答4:


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")
```


来源:https://stackoverflow.com/questions/45591286/for-r-markdown-how-do-i-display-a-matrix-from-r-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!