r - 为什么 ggplotly 在 rmarkdown 中不能像 ggplot 一样工作
问题描述
我想以ggplotly
同样的方式使用它的副作用,ggplot
甚至graphics
这样做。我的意思是当我knitr::knit
或rmarkdown::render
Rmd 文档时,我希望报告中的对象print(obj)
在哪里,但事实并非如此。obj
ggplotly
- 谁能解释发生了什么?
- 谁能告诉我如何实现我想做的事情。我希望能够在不返回对象的情况下将 ggplotly 图绘制到函数中(我想返回图的基础数据),并且我希望代码适用于 ggplot 和 ggplotly(即使用相同的代码一个ggplot或ggplotly)
问题.R文件
#+ libs, echo = FALSE
suppressMessages({
library(ggplot2)
library(plotly)
library(rmarkdown)
})
#+ functions decl, echo = FALSE
df <- data.frame(x = 1:5, y = 1:5)
f_0 <- function(df) {
p <- ggplot(df, aes(x, y)) + geom_line()
# p or plot(p) or print(p) works
print(p)
return(df)
}
f_1 <- function(df) {
p <- ggplot(df, aes(x, y)) + geom_line()
p <- ggplotly(p)
# plot(p) crashes
# print p does not print in report
print(p)
# p standalone does not work either
p
return(df)
}
#' # plots
#' plot 0
#+ plot_0
res_0 <- f_0(df)
#' plot 1
#+ plot_1
res_1 <- f_1(df)
渲染这个文件
rmarkdown::render("question.R")
输出
解决方案
编辑评论:作为一种风格,将计算和绘图分离成不同的函数通常是一个好主意,因为它增加了模块化,使代码更易于维护,并允许在没有参数蠕变的情况下进行更精细的控制。然后可以轻松地将各个函数的输出映射到单独的 knitr 块。
最佳解决方案:我知道您特别询问不返回绘图对象,但我只想指出,将它与结果一起返回提供了最干净、最优雅的解决方案:
---
output: html_document
---
```{r include=FALSE}
library( tidyverse )
df <- data_frame( x=1:5, y=1:5 )
```
```{r}
f <- function(df) {
gg <- ggplot(df, aes(x,y)) + geom_point()
list( result=df, plot=plotly::ggplotly(gg) )
}
res <- f(df)
res$plot
```
但是,如果您绝对不能从函数返回一个 plotly 对象,您有一些选择。
选项 1:将 plotly 对象存储到父框架,提供从 knitr 块对其的访问。
```{r}
f1 <- function(df) {
gg <- ggplot(df, aes(x,y)) + geom_point()
assign("ggp", plotly::ggplotly(gg), envir=parent.frame())
df # NOT returning a plot
}
res1 <- f1(df)
ggp # Let knitr handle the rendering naturally
```
选项 2:将绘图渲染为临时 .html,然后将其作为 iframe 导入
```{r, results='asis'} # <-- note the "asis" chunk option
f2 <- function(df)
{
gg <- ggplot(df, aes(x,y)) + geom_point()
htmlwidgets::saveWidget( plotly::ggplotly(gg), "temp.html")
print( htmltools::tags$iframe(src="temp.html", width=640, height=480) )
df # NOT returning a plot
}
res2 <- f2(df)
```
解释:如果我错了,易辉可以纠正我,但knitr基本上是在幕后做“选项2”。它将 htmlwidgets(例如 plotly 对象)渲染到临时 .html 文件中,然后组合这些临时文件以生成最终文档。它在函数内失败的原因是当执行离开函数范围时临时文件被删除。(您可以通过使用tempfile()
而不是 persistent自己复制此内容"temp.html"
;该iframe
对象将在最终文档中显示“找不到文件”错误。)可能有一种方法可以修改 knitr 挂钩以保留临时文件,但这超出了我的知识范围。最后,基本对象没有这个问题的原因ggplot
是因为它们的输出到绘图设备,
推荐阅读
- discord.js - 有没有办法用命令切换事件?
- groovy - Groovy 使用 Apache POI 从 xlsx 获取值
- javascript - POST 请求始终为空
- c# - 获取列索引作为常量值
- flutter - Flutter 小部件组合 - 嵌套列表视图
- sql - Teradata:将varchar转换为十进制/浮点数
- docker - 在 Docker 中运行 Firecracker
- ios - 为什么移动动画时无法选择annotationView
- laravel - 从 Laravel 应用程序读取 Codeigniter 外部文件夹
- c# - WPF Webbrowser 控件中保存的表单数据的位置