【问题标题】:Can knitr dynamically output narrative text based on R code results in each chunk?knitr可以根据每个chunk中的R代码结果动态输出叙述文本吗?
【发布时间】:2016-01-04 21:15:41
【问题描述】:

我正在考虑开发一个 .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

.....

【问题讨论】:

  • `r cat(c('text1, 'text2')[x])` ?
  • 你的问题的答案是yes,可以做到,方法很多。
  • @BryanHanson 谢谢布莱恩,你介意举一两个例子来说明一下吗?非常感谢。
  • @arvi1000 谢谢!实际上你的方式确实有效。
  • knitr 网站上有很多例子。除非我误解了您的要求,否则您所描述的正是knitr 的重点和目的。如果您可以在 R 中完成,您可以在 knitr 中完成。您会发现它是一个非常有用的工具。

标签: r knitr r-markdown


【解决方案1】:

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

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

  • eval
  • echo
  • results
  • engine

eval 判断一个块是否被评估; eval = FALSE 跳过该块。 echo 决定是否显示块的源代码。 results 确定如何处理块的输出。默认情况下 (results = "markup) 使用输出挂钩将特定于文档类型的标记应用于输出。 results = "asis" 表示所有输出都“按原样”包含在输出文件中,没有任何修改。

通过这三个选项,可以完成以下工作:

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 可用于评估块,其中包括(当前未记录?)引擎asis。这个引擎非常简单。来自knitr NEWS file

添加了一个名为asis的新引擎,用于写入块内容而不对其进行处理;它还尊重块选项echoeval——当其中一个是FALSE 时,块将被隐藏;这使得有条件地编写文本成为可能

asis 引擎与以下语法糖 (source) 结合使用

对于语言引擎,R Markdown 代码块头的语法现在可以是```{lang, option=value}`(例如```{python}```{Rcpp}),相当于```{r, engine='lang', option=value}

上面的例子变成:

This is some text ...

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

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

【讨论】:

  • 谢谢@CL。为您解答。但是,您的解决方案将以相同的文本格式打印该代码块中的任何其他内容,而不像默认代码输出。我将添加我的解决方案。
  • @Asieh 是的,这是故意的。这个问题的重点与你的略有不同。我只是在您感兴趣的情况下链接它。
  • 对于有条件显示的短文本片段,this answer 提供了一个非常有用的解决方案。
【解决方案2】:

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

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

编辑: 因为这被选为答案。我会详细说明。 您可以使用 if() 或 ifelse() 或 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...

【讨论】:

  • 问题是关于条件输出。因此,您需要至少向内联表达式添加一个if(condition)。另请注意,我的回答可能非常冗长,但底线与上一个示例中所示的一样简单(带有asis, echo = ...} 的块)。
【解决方案3】:

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

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

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

【讨论】:

  • 你最好在你自己的问题中添加这个(到你现有的答案);我认为它不属于这里。
猜你喜欢
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
  • 2016-08-19
相关资源
最近更新 更多