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)}
```
我正在考虑开发一个 .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 optionsecho
andeval
-- when either one isFALSE
, 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)}
```