【问题标题】:R Shiny: code output inside markdown table cellR Shiny:markdown表格单元格内的代码输出
【发布时间】:2021-06-06 04:38:51
【问题描述】:

我正在尝试将 R 批次输出嵌入到 html 表格的单元格中。这是据我所知:

app.R

require(shiny)
require(knitr)
require(ggplot2)

d = iris

ui = fluidPage(
  uiOutput('markdown')
)

server = function(input, output, session) {
  output$markdown <- renderUI({
    HTML(knit(text = paste(readLines('table.html'), collapse='\n')))
  })
}

shinyApp(ui, server)

table.html

<table class='table'>
<tr> <th>text field</th> <th>sparkline</th> </tr>
<tr>
  <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</td>
  <td>
```{r, echo=FALSE, include=TRUE}
# message("setosa") # uncomment to test console output
qplot(Sepal.Length, Sepal.Width, data = d[d == "setosa",], geom="line")
```
  </td>
</tr>

<tr>
  <td>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</td>
  <td>
```{r, echo=FALSE, include=TRUE}
# message("versicolor")
qplot(Sepal.Length, Sepal.Width, data = d[d == "versicolor",], geom="line")
```
  </td>
</tr>

<tr>
  <td>Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</td>
  <td>
```{r, echo=FALSE, include=TRUE}
# message("virginica")
qplot(Sepal.Length, Sepal.Width, data = d[d == "virginica",], geom="line")
```
  </td>
</tr>
</table>

输出如下:

knit 正在将图形输出到文件。有没有办法让它们直接渲染? 我可能正在处理这个错误,但尚未确定等效的 {rmarkdown} 工作流程..


在使用message(...) 输出而不是 qplot 进行测试时,html 表格单元格如下所示:

``` ## setosa ```

知道如何删除反引号和井号吗?

【问题讨论】:

    标签: r shiny r-markdown knitr


    【解决方案1】:

    一个工作的工具链如下:

    table.Rmd

    <!--pandoc
    t: html
    o: table.html
    -->
    
    ```{r, echo = FALSE, include = FALSE}
    opts_knit$set(base.dir = "www")
    ```
    <table class='table'>
      <tr>
        <th>text field</th>
        <th>sparkline</th>
      </tr>
      <tr>
        <td>
           Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
        </td>
        <td>
          ```{r, echo = FALSE, include = TRUE}
          qplot(Sepal.Length, Sepal.Width, data = d[d$Species == "setosa", ], geom = "line")
          ```
        </td>
      </tr>
    </table>
    

    app.R

    library(shiny)
    library(knitr)
    library(ggplot2)
    
    d <- iris
    ui <- fluidPage(
       uiOutput("markdown")
    )
    
    server <- function(input, output, session) {
       output$markdown <- renderUI({
          tmp <- knit("table.Rmd", quiet = TRUE) ## could combine these...
          pandoc(tmp)                            ## ...two lines also in `knit2pandoc`
          includeHTML("table.html")
       })
    }
    
    shinyApp(ui, server)
    

    然后你可以运行runApp("app.R"),你会得到以下输出:

    一些备注

    这比我想象的要棘手,而且我绝不是 pandoc/knit/markdown 专家,所以我什至不确定我的命名是否正确,但我可以分享我的发现:

    • 我将您的table.html 更改为table.Rmd,因为它实际上是RMarkdown 而不是(纯)HTML 文件。如果我们想要(如我的示例)使用文件名而不是 readLines,这对于帮助 knit 使用正确的分隔符也是必要的。
    • 我运行了knit("table.Rmd") 来查看markdown 文档的外观,并且看起来还可以。
    • 我的下一个想法是在这个.md 文件上使用includeMarkdown,但经过反复试验,我发现无论出于何种原因,从.md -> .html 的翻译(这就是引擎盖下发生的事情对于includeMarkdown) 不起作用,并且降价令牌![plot](path/to/figure) 从未根据&lt;img&gt; 标签正确转换为teh。当我尝试使用knit2html 时也发生了同样的情况。两者都依赖于markdown::renderMarkdown,并且此函数根本不会将降价图像标记转换为 HTML 图像标记如果嵌套在表格中
    • 查看独立的rmarkdown 文档,我发现他们使用pandocmarkdown 文档转换为HTML 格式。
    • 经过反复试验,我可以说服pandoc 产生结果:
      • 我在table.Rmd 中添加了一些pandoc 配置。但是,因为无论如何这些都是默认值,您也可以放心地忽略它们。如果你想做一些更花哨的东西,你需要他们调整pandoc 的调用方式。
      • shiny 期望静态资源托管在 www 文件夹下。因此,我们需要告诉knit 使用此文件夹来存储数字(另一种选择是在shiny 一侧使用addResourcePath)。

    TL;DR

    以下工具链将起作用:

    table.Rmd -> table.md via knit -> table.html via pandoc -> shiny via inclueHTML
    

    或等价

    table.Rmd -> table.html via knit2pandoc -> shiny via includeHTML
    

    renderMarkdown 不喜欢表中的块

    does_translate <- "```{r}\nggplot2::qplot(1, 2)\n```"
    does_not_translate <- "<table><tr><td>\n```{r}\nggplot2::qplot(1, 2)\n```\n</td></tr></table>"
    
    cat(knit2html(text = does_translate, fragment.only = TRUE))
    # vs.
    cat(knit2html(text = does_not_translate, fragment.only = TRUE))
    
    

    更新

    根据 cmets,如果您想确保在块中生成的文件名是“唯一的”,您可以在 Rmd 中使用以下代码块(受 this article 启发):

    ```{r, echo = FALSE, include = FALSE}
    opts_knit$set(base.dir = "www")
    
    knitr::opts_chunk$set(
       fig.process = function(filename) {
          wd <- dirname(filename)
          ext <- file_ext(filename)
          new_filename <- tempfile(tmpdir = wd, fileext = paste0(".", ext))
          file.copy(filename, new_filename)
          unlink(filename)
          ifelse(file.exists(new_filename), new_filename, filename)
       }
    )
    
    ```
    

    【讨论】:

    • 太棒了,非常感谢@thothal。显然,为此付出了一些努力。只是想:我注意到这会在www/figure/unnamed-chunk-2-1.png 生成一个文件。我想知道多个同时用户与同一个文件发生冲突的风险(例如,当他们的 d 对象是不同的数据时)。有什么想法吗?
    • 我不是shiny 如何在不同用户之间共享空间的专家。不过,您可以配置 pandoc 来创建独立的 html 文件。在这种情况下,图片是base64 编码的,不包含在链接中。假设shiny 不处理这个问题,您还可以为块生成的图形分配随机名称。将为此提供一个示例。
    猜你喜欢
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多