Rmarkdown (knitr chunk) 文档中生成的多个 (R) plotly 图形

multiple (R) plotly figures generated in a Rmarkdown (knitr chunk) document

我尝试使用循环或 lapply 在 Rmarkdown 文档中创建多个绘图图形。

R 脚本:

require(plotly)
data(iris)
b <- lapply(setdiff(names(iris), c("Sepal.Length","Species")),
            function(x) {
              plot_ly(iris, 
                      x = iris[["Sepal.Length"]],
                      y = iris[[x]], 
                      mode = "markers")
            })
print(b)

效果很好,但当包含在 knitr 块中时会失败:

---
output: html_document
---

```{r,results='asis'}
require(plotly)
data(iris)
b <- lapply(setdiff(names(iris), c("Sepal.Length","Species")),
            function(x) {
              plot_ly(iris, 
                      x = iris[["Sepal.Length"]],
                      y = iris[[x]], 
                      mode = "markers")
            })
print(b)
```

我尝试用 lapply evalparse 的组合替换 print(b) 但只显示了最后一个数字。

我怀疑 scoping/environment 有问题,但我找不到任何解决方案。

我找到了一个 "dirty" 解决方案,方法是使用临时文件并编织它:

```{r,echo=FALSE}
mytempfile<-tempfile()
write("```{r graphlist,echo=FALSE}\n",file=mytempfile)
write(paste("p[[",1:length(p),"]]"),file=mytempfile,append = TRUE)
write("\n```",file=mytempfile,append = TRUE)
```

`r knit_child(mytempfile, quiet=T)`

但不尽如人意

而不是print(b),将b放在htmltools::tagList()中,例如

```{r}
library(plotly)

b <- lapply(
  setdiff(names(iris),
          c("Sepal.Length","Species")),
  function(x) {
    plot_ly(iris, 
            x = iris[["Sepal.Length"]],
            y = iris[[x]], 
            mode = "markers")
  }
)

htmltools::tagList(b)
```

注意: 在 Plotly v4 之前,必须使用 Plotly 的 as.widget() 函数将 Plotly 对象转换为 htmlwidgets。从 Plotly v4 开始,它们默认是 htmlwiget 对象。

对技术背景感兴趣的朋友可以看看this blog post of mine。简而言之,只有 top-level 表达式被打印出来。

对于任何在循环中苦苦挣扎的人,以下是对我有用的方法。

p=list()
for (n in 1:3){
  p[[n]] <- plot_ly(x = 1:100, y = rnorm(100)+n, mode = 'lines', type="scatter")
}
htmltools::tagList(p)

即列表 p 是在循环中创建还是在 lapply 中创建都没有关系,只要您在循环外调用 htmltools::tagList

感谢 Yihui 帮助我实现目标,感谢他们在开发和帮助使用这些工具方面所做的大量工作。