r - 在 Rmarkdown 中动态创建选项卡对 ggplot 不起作用,而对 plotly 起作用

标签 r ggplot2 r-markdown knitr ggplotly

我一直愿意动态创建tab rmarkdown 中的内容.
我创建了一个 in_tabs这似乎适用于除 ggplot 之外的所有事情地块。
它的工作方式是创建 Rmd在选项卡中显示嵌套列表所需的代码。
以下可重现的示例显示了该问题:

---                                                                                                                                    
title: "test"                                                                                                                          
output: html_document                                                                                                                  
---                                                                                                                                    
                                                                                                                                       
```{r setup, include = FALSE}                                                                                                          
library(ggplot2)                                                                                                                       
library(plotly)                                                                                                                        
l1 <- list(p1 = data.frame(x=1:10, y=1:10))                                                                                            
l2 <- list(p2 = data.frame(x=100:110, y=100:110))                                                                                      
gplot <- function(data) {                                                                                                              
    p <- ggplot(data) + aes(x=x, y=y) + geom_point() + geom_line()                                                                     
    return(p)                                                                                                                          
}                                                                                                                                      
gplotly <- function(data) {                                                                                                            
    p <- ggplot(data) + aes(x=x, y=y) + geom_point() + geom_line()                                                                     
    return(ggplotly(p))                                                                                                                
}                                                                                                                                      
```                                                                                                                                    
                                                                                                                                       
```{r, code, include = FALSE}                                                                                                          
in_tabs <- function(l, labels = names(l), level, knit = TRUE, close_tabset = FALSE) {                                                  
    if(is.null(labels)) {                                                                                                              
        stop("labels are NULL, it is required not to be so that the tabs have proper names")                                           
    }                                                                                                                                  
    names(l) <- labels                                                                                                                 
    rmd_code <- lapply(seq_along(l), FUN = function(i) obj_to_rmd(l[[i]], name = names(l)[i], level = level + 1L))                     
    if(isTRUE(getOption("knitr.in.progress"))) {                                                                                       
        res <- knitr::knit(text = unlist(rmd_code), quiet = TRUE)                                                                      
        cat(res)                                                                                                                       
    } else {                                                                                                                           
        if(!knit) {                                                                                                                    
            cat(unlist(rmd_code))                                                                                                      
        } else {                                                                                                                       
            return(l)                                                                                                                  
        }                                                                                                                              
    }                                                                                                                                  
    if(close_tabset) {                                                                                                                 
        cat(paste(get_section(level), "{.unlisted .unnumbered .toc-ignore .tabset}", "\n"))                                            
    }                                                                                                                                  
}                                                                                                                                      
                                                                                                                                       
get_section <- function(level) {                                                                                                       
    paste(rep("#", times = level), collapse = "")                                                                                      
}                                                                                                                                      
                                                                                                                                       
get_tabset <- function(obj) {                                                                                                          
    ifelse(inherits(obj, "list"), "{.tabset}", "")                                                                                     
}                                                                                                                                      
                                                                                                                                       
obj_to_rmd <- function(obj, parent_name = "l", name, level) {                                                                          
    section_code <- sprintf("%s %s %s\n", get_section(level), name, get_tabset(obj))                                                   
    if(!inherits(obj, "list")) {                                                                                                       
            rmd_code <- c("```{r, echo = FALSE}\n",                                                                                    
                          sprintf("%s$`%s`\n", parent_name, name),                                                                     
                          "```\n",                                                                                                     
                          "\n")                                                                                                        
    } else {                                                                                                                           
        rmd_code <- c("\n",                                                                                                            
                      lapply(X = seq_along(obj),                                                                                       
                             FUN = function(i) obj_to_rmd(obj[[i]], sprintf("%s$`%s`", parent_name, name), names(obj)[i], level + 1L)))
    }                                                                                                                                  
    return(c(section_code, rmd_code))                                                                                                  
}                                                                                                                                      
```                                                                                                                                    
                                                                                                                                       
                                                                                                                                       
# plot 1 {.tabset}                                                                                                                     
```{r, plot-01, results = "asis"}                                                                                                      
in_tabs(lapply(l1, FUN = gplot), labels = names(l1), level = 1L)                                                                       
```                                                                                                                                    
                                                                  
# plot 2 {.tabset}                                                
```{r, plot-02, results = "asis"}                                 
in_tabs(lapply(l2, FUN = gplot), labels = names(l2), level = 1L)  
```                                                               
                                                                  
# plot 3 {.tabset}                                                
```{r, plot-03, results = "asis"}                                 
in_tabs(lapply(l1, FUN = gplotly), labels = names(l1), level = 1L)
```                                                               
                                                                  
# plot 4 {.tabset}                                                
```{r, plot-04, results = "asis"}                                 
in_tabs(lapply(l2, FUN = gplotly), labels = names(l2), level = 1L)
```   

                                                        
我得到的输出是:
你可以看到第一个情节实际上与第二个情节相同的问题,而它不应该!!!
enter image description here
使用时 plotly (或我测试过的其他任何东西)它按预期工作,如图 3 和图 4 所示
enter image description here
你能帮我修复它吗,我很高兴测试对象的类 obj_to_rmd收到。
PS:rmd代码 in_tabs通过运行 in_tabs(..., knit = FALSE) 可以看到生成.例如
in_tabs(lapply(l1, FUN = gplot), labels = names(l1), level = 1L, knit = FALSE)
## p1 
 ```{r, echo = FALSE}
 plot(l$`p1`)
 ```

最佳答案

正如 stefan 提到的,问题在于 ggplot 的 id,因为它们以某种方式具有相同的代码块,即使您对块的命名不同。我不知道这种行为的原因,但您可以通过设置绕过它

```{r, include=FALSE}
options(knitr.duplicate.label = "allow")
```
在文档的开头。这应该够了吧。它将为您的每个图提供不同的块名称。您可以通过删除 results = "asis" 来验证这一点。从您的 ggplots 中可以看到它们不再具有相同的 ID。
enter image description here
## ## p1 
## 
## <img src="test_files/figure-html/unnamed-chunk-2-1.png" width="672" />


## ## p2 
## 
## <img src="test_files/figure-html/unnamed-chunk-1-2-1.png" width="672" />
您可以在 bookdown.org 阅读更多关于允许重复块的信息。

关于r - 在 Rmarkdown 中动态创建选项卡对 ggplot 不起作用,而对 plotly 起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69353667/

相关文章:

r - 在 Ubuntu 16 上安装 R 语言 - 未满足的依赖项

r - 在 R 中使用 ggplot2 在分类散点图中添加水平线

r - 将grid.text添加到arrange.grob以导出为PNG

html - "Undefined"RMarkdown 选项卡集中包含选项卡?

r - 在 R 中将 data.frame 转换为时间序列对象时遇到困难?

r - 根据规则用其他值替换数据框中的值

r - 使用 ncdf4::ncvar_get 时如何指定维度顺序?

r - 如何更改 stat_boxplot (误差条)的宽度

r - 将 2 个大列分成两部分

r - 内部带有管道的 pander Markdown 表未正确处理