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

前端 未结 4 1103
没有蜡笔的小新
没有蜡笔的小新 2021-02-05 23:14

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          


        
相关标签:
4条回答
  • 2021-02-05 23:31

    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
    ```
    
    0 讨论(0)
  • 2021-02-05 23:38

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

    0 讨论(0)
  • 2021-02-05 23:47

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

    0 讨论(0)
  • 2021-02-05 23:49

    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")
    ```
    
    0 讨论(0)
提交回复
热议问题