【问题标题】:Conditionally display a block of text in R Markdown有条件地在 R Markdown 中显示一个文本块
【发布时间】:2014-10-13 22:50:28
【问题描述】:

我正在使用 knitr 解析 R Markdown 文档。有没有办法根据我传递给 knitr 的环境中的变量有条件地在 R Markdown 中显示一段文本?

比如:

`r if(show.text) {`
  la la la
`r }`

如果show.text 为真,将在结果文档中打印“la la la”。

【问题讨论】:

标签: r knitr r-markdown


【解决方案1】:

你需要一个完整的 R 表达式,所以你不能像你展示的那样把它分成多个块,但是如果一个块的结果是一个文本字符串,那么它将按原样包含(不带引号),所以你应该能够做类似的事情:

`r if(show.text){"la la la"}`

当且仅当show.textTRUE 时它才会包含文本。

【讨论】:

  • 这太棒了,应该被接受。甚至扩展到更复杂的降价输入,例如`r if(TRUE){"#Header\nIs this under the header\n\n##subheader\nis this undersub?"}`
  • 我特别喜欢这个解决方案,因为在某些情况下,很难让换行符正常运行。有时,在文档主体中插入条件文本比在带有results = "asis" 的代码块中更容易,因此您不必弄乱\n<br>、@987654328 的无休止尝试@等
【解决方案2】:

您可以使用“eval”块选项来执行此操作。见http://yihui.name/knitr/options/

```{r setup, echo=FALSE}
show_text <- FALSE
````

```{r conditional_block, eval=show_text}
print("this will only print when show.text is TRUE")
```

我一直在使用YAML 配置文件来参数化我的降价报告,这使得它们更易于重用。

```{r load_config}
library(yaml)
config <- yaml.load_file("config.yaml")
```

...

```{r conditional_print, eval=config$show_text}
print("la la la")
````

【讨论】:

【解决方案3】:

我发现最简单的方法是将我的所有文本放入一个单独的文件中,然后将其从主文件中包含:

```{r conditional_print, child='text.Rmd', eval = show_text}
```

这样做的好处是您仍然可以将内联 R 语句或其他块放入子文件中,因此,如果您改变了关于什么是可选文本的想法,则不必重构您的项目。

【讨论】:

  • 我喜欢你的解决方案。这使得处理更大的报告更容易管理。
【解决方案4】:

这是对 Paul Boardman 方法的调整,可在输出中提供适当的标记。

```{r setup, echo=FALSE}
show_text <- FALSE
```

```{r conditional_block, echo=FALSE, results='asis', eval=show_text}
cat("## Hey look, a heading!

lorem ipsum dolor emet...")
```

更好的是,如果我们调用 python 引擎来生成我们的输出,我们可以使用三引号来轻松处理包含单引号或双引号的文本,而无需做任何花哨的事情:

```{python, conditional_block_py, echo=FALSE, results='asis', eval=show_cond_text}
print("""
## Still a heading

Block of text with 'single quotes' and "double quotes"
""")
```

【讨论】:

  • 我很欣赏 Python 解决方案,但如果您还需要在该代码块中使用 R 对象,这会很困难。
  • @ctbrown 如果您需要从 Markdown 内部运行 R 代码,例如cat("This year, we sold `r quarterlySales` units of product") 那么我在这里介绍的 python 解决方案和 R 解决方案都不适合你。您可以通过分段粘贴内容来构建所需的文本,而不是尝试直接在降价中调用 R 代码,例如cat(paste("This year, we sold", quarterlySales, "units of product"))。如果这不是您的意思,请随时详细说明您的用例,我会看看我能想出什么。
  • 这很棒,非常适合我的需要。条件块似乎只在编织输出时才起作用。它不会让我突出显示块中的一行代码并执行它,每次都报告错误并中止 R 会话。 {r conditional_block, echo=FALSE, results='asis', eval=show_text} cat("## Hey look, a heading! lorem ipsum dolor emet...") Error in class(obj) &lt;- "rs.scalar" : cannot set attribute on a symbol 在正常的 R 块中它可以工作 {r} cat("## Hey look, a heading! lorem ipsum dolor emet...") 任何想法为什么?
  • knitr asis 引擎是为此 bookdown.org/yihui/rmarkdown-cookbook/eng-asis.html 制作的,它避免使用 cat 并出现引用问题。
【解决方案5】:

对于较大的文本块,上述解决方案可能有点笨拙,在某些情况下不是很好。假设我想为有一些问题的学生创建一个工作表,并使用相同的 .Rmd 文件生成一个包含解决方案的文件。我使用了基本的 LaTeX 流控制:

``` {r, include = F}
# this can be e.g., in a parent .Rmd and the below can be in child
solution <- TRUE 
```
\newif\ifsol
\sol`r ifelse(solution, 'true', 'false')`

那我可以做:

What is $2 + 2$

\ifsol
4
\fi

这样您还可以使用

创建替代文本块
\ifsol
Alternative 1
\else
Alternative 2
\fi

【讨论】:

  • 嗨米兰:我试图复制你的想法,但没有成功(Alternatives 都打印出来了)。我很想能够让它工作!我的代码都在一个 Rmd 之下(没有孩子)。有什么想法吗?如有任何帮助,我将不胜感激。
  • 嗨@MarianMinar,我只是将上面的代码复制到一个新的.Rmd 中,它工作得很好。确保在 R 代码块中创建 solution 对象,因为它习惯于将 \sol 设置为 true 或 false。
  • @MilanValášek:对我来说,它不适用于 HTML,只能在 LaTex 中使用。如果你找到一个和你的 HTML 一样漂亮和简单的解决方案,我会非常感兴趣!
  • @mavericks 是的,我刚刚开始解决同样的问题。如果有人可以提供帮助,那就太好了!
  • @mavericks 我最终编写了一个函数,该函数进行了大量的后处理,与下面的 Tommi Härkänen 所做的没什么不同。然而,一个简单但不是非常优雅的解决方案是将 LaTeX ifelse 替换为 R if-else 语句,这些语句在您的替代块周围插入(或不插入)HTML 注释标记“”的文本。注释掉的文本仍会在 HTML 文件中,但不会可见。你甚至可以为自己编写一个函数,让它更有效率……
【解决方案6】:

上面接受的答案适用于内联内容。

对于块内容(Markdown 文本的几个段落之一),knitr 包含一个asis 引擎,允许根据块选项echo = FALSEecho = TRUE 有条件地包含Markdown 内容

来自文档https://bookdown.org/yihui/rmarkdown-cookbook/eng-asis.html的示例

```{r}
getRandomNumber <- function() {
  sample(1:6, 1)
}
```

```{asis, echo = getRandomNumber() == 4}
According to https://xkcd.com/221/, we just generated
a **true** random number!
```

如果您需要包含更复杂的内容,例如带有代码块的 R Markdown 文档,那么子文档可能会很有用。见https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html

【讨论】:

    【解决方案7】:

    另一种有条件地添加降价文本的方法如下。它使用block“引擎”,虽然我不确定如何使内联 R 评估工作,但它似乎运行良好。

    请注意,我使用 YAML 元数据中定义的 view_all 开关来控制块是否可见。

    另外,请注意evalinclude 块选项都是必需的。 第一个防止在 RStudio 中的常规 Run All 期间出现错误。 第二个阻止了 Knit 的输出。

    ---
    title: "Conditional Output"
    params:
      view_all: false
    output:
      html_document: default
      pdf_document: default
    ---
    
    ```{block eval=FALSE, include=params$view_all}
    # Some simple markdown.
    
    Some things work: $2 + 2^2 = 3\cdot2$
    
    Other does not: 2 + 2 = `r 2+2`
    ```
    

    【讨论】:

    • 这些include= 参数是否可以在 Shiny rmarkdown 文档的反应上下文中以某种方式选择?
    • block 引擎应该用于此目的。它可能会在未来中断,因为它的预期引擎是asis 引擎。看我的回答stackoverflow.com/a/66454300/3436535
    【解决方案8】:

    我尝试定义一个函数my.render(),它预处理Rmd 文件,并根据commentout 参数,将HTML 注释代码(TRUE) 保留在Rmd 文件中或删除它们(FALSE )。然后将预处理后的Rmd文件写入tmp.Rmd,并使用常用的render()函数。

    my.render <- function(input, commentout=FALSE, ...) {
      if (commentout == FALSE) {
        ## Delete the HTML comment lines from code
        txt <- readLines(input)
        txt[grepl(" *<!-- *| *--> *", txt)] <- ""
        write.table(txt, file="tmp.Rmd", sep="\n", quote=FALSE, row.names=FALSE, col.names=FALSE)
        render("tmp.Rmd", output_file=sub("Rmd","html",input), ...)
      } else {
        render(input, output_file=sub("Rmd","html",input), ...)
      }
    }
    

    这似乎奏效了。例如

    <!--
    This text with formulas $\alpha+\beta$ is visible, when commentout=FALSE.
    -->
    

    【讨论】:

      猜你喜欢
      • 2016-01-01
      • 1970-01-01
      • 2021-08-06
      • 1970-01-01
      • 2020-11-30
      • 2022-08-18
      • 2019-10-22
      • 2018-05-21
      • 1970-01-01
      相关资源
      最近更新 更多