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
eval
和 parse
的组合替换 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 帮助我实现目标,感谢他们在开发和帮助使用这些工具方面所做的大量工作。
我尝试使用循环或 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
eval
和 parse
的组合替换 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 帮助我实现目标,感谢他们在开发和帮助使用这些工具方面所做的大量工作。