动态循环 htmlwidgets 并为 RMarkdown 添加 knitr 格式

Dynamically loop through htmlwidgets and add knitr formatting for RMarkdown

我正在尝试动态创建并循环遍历 htmlwidgets,例如 DTplotlyrbokeh,以生成自动 knitr 报告。有没有办法将 knitr 格式(例如 tabset)添加到 github 问题 https://github.com/ramnathv/htmlwidgets/pull/110 中概述的 tagList 方法中?我也在那里发布了这个问题。

下面是我所想的一些示例代码,但它并不完全有效。我想要做的是创建 10 个选项卡,每个选项卡都有一份从 plot_list 生成的图表的副本。现在发生的是所有的情节都进入最后一个选项卡。实际上,plot_list 会有不同的 plots/tables.

#' ---
#' title: htmltools::tagList test
#' output:
#'    html_document
#' ---

#' # {.tabset}
#+ results='asis', echo=FALSE
library(plotly)
library(printr)

plot_list = lapply(1:10, 
                   function(i){ 
                     as.widget(plot_ly(iris, 
                                       x = iris[["Sepal.Length"]],
                                       y = iris[["Sepal.Width"]], 
                                       mode = "markers")) 
                    } 
                  )

htmltools::tagList( lapply(1:10, 
                            function(i) {
                              pandoc.header(paste0("Tab",i,' {.tabset}'), 2)
                              plot_list[[i]]
                            } 
                          )
                   )

# rmarkdown::render("your_path/htmltoolsTagList_test.r")

之前,我成功地用嵌套的 for 循环做了类似的事情,但是一旦我尝试使用具有 HTML 依赖关系的图形,图形当然不会呈现,因为它们不再是顶级表达式。在knitr中是否可以这样循环?

我的一个后续问题是:假设我想将这些选项卡嵌套到另一组以相同方式创建的选项卡中,这可能吗?我想问的是,我可以使用类似于嵌套 for 循环的方法动态嵌套选项卡吗?

我仍在学习如何使用 knitr,非常感谢您的帮助! 谢谢!

我将在下面复制我对 Github 问题的回复。

问得好,我认为这次讨论会帮助其他人。在没有 rmarkdown.

帮助的情况下,从头开始构建类似于您提出的建议可能是最简单的方法

手动构建

# https://github.com/ramnathv/htmlwidgets/pull/110#issuecomment-216562703

library(plotly)
library(htmltools)
library(markdown)
library(shiny)

browsable(
  attachDependencies(
    tagList(
      tags$div(
        class="tabs",
        tags$ul(
          class="nav nav-tabs",
          role="tablist",
          tags$li(
            tags$a(
              "data-toggle"="tab",
              href="#tab-1",
              "Iris"
            )
          ),
          tags$li(
            tags$a(
              "data-toggle"="tab",
              href="#tab-2",
              "Cars"
            )
          )
        ),
        tags$div(
          class="tab-content",
          tags$div(
            class="tab-pane active",
            id="tab-1",
            as.widget(
              plot_ly(
                iris,
                x = iris[["Sepal.Length"]],
                y = iris[["Sepal.Width"]], 
                mode = "markers"
              )
            )
          ),
          tags$div(
            class="tab-pane",
            id="tab-2",
            as.widget(
              plot_ly(
                cars,
                x = speed,
                y = dist, 
                mode = "markers"
              )
            )
          )
        )
      )
    ),
    # attach dependencies
    #  see https://github.com/rstudio/rmarkdown/blob/master/R/html_document.R#L235
    list(
      rmarkdown::html_dependency_jquery(),
      shiny::bootstrapLib()
    )
  )
)

在 rmarkdown

可能有更好的方法来完成这项工作,但在有人让我明白之前,我们可以采用上面的方法并在 rmarkdown 中使用它。不幸的是,这仍然是非常手动的。如需更多参考,这里是 RStudio 用来构建 tabsets.

code
---
title: "tabs and htmlwidgets"
author: "Kent Russell"
date: "May 3, 2016"
output: html_document
---

```{r echo=FALSE, message=FALSE, warning=FALSE}
library(plotly)
library(htmltools)
library(magrittr)

# make a named list of plots for demonstration
#  the names will be the titles for the tabs
plots <- list(
  "iris" = plot_ly(
    iris,
    x = iris[["Sepal.Length"]],
    y = iris[["Sepal.Width"]], 
    mode = "markers"
  ),
  "cars" = plot_ly(
    cars,
    x = speed,
    y = dist, 
    mode = "markers"
  )
)

# create our top-level div for our tabs
tags$div(
  # create the tabs with titles as a ul with li/a
  tags$ul(
    class="nav nav-tabs",
    role="tablist",
    lapply(
      names(plots),
      function(p){
        tags$li(
          tags$a(
            "data-toggle"="tab",
            href=paste0("#tab-",p),
            p
          )
        )
      }
    )
  ),
  # fill the tabs with our plotly plots
  tags$div(
    class="tab-content",
    lapply(
      names(plots),
      function(p){
         tags$div(
          #  make the first tabpane active
          class=ifelse(p==names(plots)[1],"tab-pane active","tab-pane"),
          #  id will need to match the id provided to the a href above
          id=paste0("tab-",p),
          as.widget(plots[[p]])
        )
      }
    )
  )
) %>%
  # attach the necessary dependencies
  #  since we are manually doing what rmarkdown magically does for us
  attachDependencies(
    list(
      rmarkdown::html_dependency_jquery(),
      shiny::bootstrapLib()
    )
  )
```