7

I'm thinking about developing a .rmd file that can dynamically write some chunks of narratives in the output file (.html,.pdf,...) based on the preceding R result. To put it simple below is how I want it works:

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

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

##if x=2 then output text below
text2

.....
Mike Wise
  • 22,131
  • 8
  • 81
  • 104
xappppp
  • 481
  • 7
  • 18
  • 4
    \`r cat(c('text1, 'text2')[x])\` ? – arvi1000 Jan 04 '16 at 21:29
  • 1
    The answer to your question is `yes`, it can be done, many ways. – Bryan Hanson Jan 04 '16 at 21:31
  • 1
    @BryanHanson Thanks Bryan, do you mind shed some light by giving one or two examples? greatly appreciated. – xappppp Jan 05 '16 at 02:43
  • @arvi1000 Thanks! actually your way does work. – xappppp Jan 05 '16 at 02:50
  • There are lots of examples at the `knitr` web site. Unless I misunderstand your request, what you describe is exactly the point and purpose of `knitr`. If you can do it in `R` you can do it with `knitr`. You'll find it a very helpful tool. – Bryan Hanson Jan 05 '16 at 03:00
  • Thanks for your reply @BryanHanson, apparently I'm not familiar with the tool good enough to know that in knitr the R code chunk and the text chunk and talk dynamically. I think I do need to read the website more thoroughly. – xappppp Jan 05 '16 at 03:07
  • There are ways to put small pieces of `R` code into text chunks, but in general, you can probably put what you are calling text into code chunks and spit it out when you want, giving the appearance of dynamic text. – Bryan Hanson Jan 05 '16 at 03:14

3 Answers3

7

When knitr processes a document, the document is split into two categories of input: ordinary text and code chunks. Ordinary text stays unchanged and is passed to the output file. Consequently, if plain text is supposed to be included dynamically, it must be inside a chunk.

Code chunks are evaluated according to their options. In the current scenario, to most important options are:

  • eval
  • echo
  • results
  • engine

eval determines whether a chunk is evaluated; eval = FALSE skips the chunk. echo determines whether to source code of the chunk is displayed. results determines how the output of a chunk is treated. By default (results = "markup) a output hook is used to apply document-type-specific markup to the output. results = "asis" means that all output is included in the output file "as-is", without any modifications.

With these three options, the following could be accomplished:

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.")
```

Output:

This is some text ...



... that is dynamically generated.

Note that the first chunk is not evaluated because eval = FALSE.

However, it is cumbersome to cat() lots of text from a R chunk. engine can be used to overcome this. Besides R, there are 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

Combining the asis engine with the following syntactic sugar (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}

the example from above becomes:

This is some text ...

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

```{asis, echo = TRUE}
... that is dynamically generated.
```
CL.
  • 14,577
  • 5
  • 46
  • 73
  • Thanks @CL. for your answer. However, your solution will print anything else in that code chunk in the same text format and not like default code output. I will add my solution. – asiehh Feb 24 '16 at 19:05
  • @Asieh Yes, this is intentional. This question has a slightly different focus than yours. I only linked it in case you were interested. – CL. Feb 24 '16 at 19:08
  • For short fragments of text that is to be displayed conditionally, [this answer](http://stackoverflow.com/a/25407811/2706569) provides a very useful solution. – CL. Dec 07 '16 at 15:50
2

The above answer is all good and well, but complicated. Use inline code, like suggested in comment.

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

Edit: Since this was selected as the answer. I'll elaborate. You can use if() or ifelse() or switch(). I like switch the most, faster and cleaner code. However I am unsure how to use an else statement in the switch.

```{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...
Helgi Guðmundsson
  • 736
  • 1
  • 6
  • 18
  • The question was about *conditional* output. So you need to add at least an `if(condition)` to the inline expression. Also note that my answer might be quite verbose, but the bottom line is as simple as shown in the last example (chunk with `asis, echo = ...}`). – CL. Jan 09 '16 at 12:35
0

The following will print the header and execute the code chunk after that header based on a variable that sets the condition (x).

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

## `r Title` 
```{r, echo=FALSE}
if(x) {print(1:5)}
```
asiehh
  • 553
  • 12
  • 22
  • You'd better add this (to your existing answer) in your own question; I don't think it belongs here. – CL. Feb 24 '16 at 19:11