knitr 能否根据每个块中的 R 代码结果动态输出叙述文本?

Can knitr dynamically output narrative text based on R code results in each chunk?

我正在考虑开发一个 .rmd 文件,它可以根据前面的 R 结果在输出文件 (.html,.pdf,...) 中动态写入一些叙述块。简单来说就是我希望它如何工作:

```{r,echo=F,include=FALSE}
x=1;

```
##if x=1 then output text below
text1

##if x=2 then output text below
text2

.....

knitr处理文档时,文档被分成两类输入:普通文本和代码块。普通文本保持不变并传递到输出文件。因此,如果要动态包含纯文本,它必须 块中。

代码块根据它们的 options 进行评估。在当前情况下,最重要的选项是:

  • eval
  • echo
  • results
  • engine

eval判断一个chunk是否被求值; eval = FALSE 跳过该块。 echo 判断是否显示chunk的源代码。 results 确定如何处理块的输出。默认情况下 (results = "markup) 输出挂钩用于将 document-type-specific 标记应用于输出。 results = "asis" 表示所有输出都包含在输出文件 "as-is" 中,没有任何修改。

有了这三个选项,可以完成以下任务:

This is some text ...

```{r, echo = FALSE, eval = FALSE, results = "asis"}
cat("... with a secret inside ...")
```

```{r, echo = FALSE, eval = TRUE, results = "asis"}
cat("... that is dynamically generated.")
```

输出:

This is some text ...



... that is dynamically generated.

请注意,第一个块未被评估,因为 eval = FALSE

但是,cat() 从 R 块中提取大量文本很麻烦。 engine 可以用来克服这个问题。除了R还有other engines that can be used to evaluate chunks, among them the (currently undocumented?) engine asis. This engine is very simple. From the knitr NEWS file:

added a new engine named asis to write the chunk content without processing it; it also respects the chunk options echo and eval -- when either one is FALSE, the chunk will be hidden; this makes it possible to write text conditionally

asis 引擎与以下语法糖 (source)

相结合

for language engines, the syntax of R Markdown code chunk headers can be ```{lang, option=value}` now (e.g. ```{python} and ```{Rcpp}), which is equivalent to ```{r, engine='lang', option=value}

上面的例子变成:

This is some text ...

```{asis, echo = FALSE}
... with a secret inside ...
```

```{asis, echo = TRUE}
... that is dynamically generated.
```

上面的答案很好,但是很复杂。使用内联代码,就像评论中建议的那样。

The mean of x is `r mean(x)` which is very high... 

编辑: 由于选择了这个作为答案。我会详细说明。 您可以使用 if() 或 ifelse() 或 switch()。我最喜欢switch,更快更干净的代码。但是我不确定如何在 switch 中使用 else 语句。

```{r}
x <- 1
```
x is `r if(x==1){"equal to one"} else {"not equal to one"}` which is great... 

x is `r ifelse(x==1, "equal to one", ifelse(x==2, "equal to two", "not equal to one or two"))` which is great... 

x is `r switch(x, "1" = "equal to one", "2" = "equal to two")` which is great...

以下将打印 header 并根据设置条件 (x) 的变量执行 header 之后的代码块。

```{r,}
x<- FALSE
Title <- ifelse(x, "My header","")
```

## `r Title` 
```{r, echo=FALSE}
if(x) {print(1:5)}
```