generate markdown comments within for loop
Asked Answered
R

3

17

I am trying to generate an HTML report, using knitr, based on an R script that has for loops. I want to generate markdown comments from the comments within the for loop, but I am not sure if it's possible.

Here is simple example, this is in test.R:

for (i in 1:5) {
    ## This is a heading for `i`
    #' This is a comment for `i`
    print(i)    
}

Then i use spin to generate a Rmd file: spin('test.R')

However, the Rmd file looks like the following.

```{r }
for (i in 1:5) {
    ## This is a heading for `i`
    #' This is a comment for `i`
    print(i)    
}
```

The markdown comments within the R chunk are not compiled into HTML. Is it possible?

Thanks, Peter

Ranch answered 18/6, 2013 at 20:58 Comment(4)
it sounds like you want to run some R code before conversion to Rmd, while as I understand it spin (followed by knit) does it the other way around. I think brew templates might help here.Inger
I think you really mean roxygen comments instead of Markdown comments. As @Inger mentioned, brew is more sophisticated for this kind of tasks (generate text from a loop).Incendiary
@Yihui, you are correct. The R file contains roxygen comments, which I hope will be converted to Markdown comments after I run spin.Ranch
@baptiste, thanks for the suggestions, I'll check out brew.Ranch
G
17

I think you can obtain what you want in knitr with the code chunk option results='asis' that you can specify after "#+" in an R script to be passed to spin (but the code looks less "clean" than the interesting brew solution proposed by @daroczig):

#+ results='asis', echo = FALSE
for (i in 1:5) {
    cat("## This is a heading for ", i, "\n")
    cat("<!-- This is a comment for ", i, "-->\n")
    print(i)    
}

If this is test.R script and that you do spin("test.R"), the resulting md file will look like that :

## This is a heading for  1 
<!-- This is a comment for  1 -->
[1] 1
## This is a heading for  2 
<!-- This is a comment for  2 -->
[1] 2
## This is a heading for  3 
<!-- This is a comment for  3 -->
[1] 3
## This is a heading for  4 
<!-- This is a comment for  4 -->
[1] 4
## This is a heading for  5 
<!-- This is a comment for  5 -->
[1] 5
Gingery answered 19/6, 2013 at 8:18 Comment(3)
this allows me to put comments into the output, but the comments are not formatted using the Markdown notation.Ranch
What do you mean by comments formatted with the markdown notation ? Is it html comments that you are looking for ? If yes, you can do it the same way, see my edited exampleGingery
(+1) I needed to include an additional cat('\n') after print(i) for headings 2 through 5 to be rendered as headings.Calgary
I
9

One solution that worked for me, is provided by how to create a loop that includes both a code chunk and text with knitr in R. By using Both results='asis' and two spaces in front of \n at the end of each loop.

example:

Without two spaces:

```{r, results='asis'}
headers <- list("We","are","your","friends")
for (i in headers){
  cat("\n##H ", i, "  \n")
  cat("comment",i)
}

Output (html):

enter image description here

As you can see, the comments and headings get messed together

Solution: With two spaces: cat(" \n") at the end of the loop

for (i in headers){
  cat("\n##H ", i, "\n")
  cat("comment",i)
  cat("  \n")# <---------------------------------
}

enter image description here

note: cat(" \n") needs to be at the very end, it does not work even if you plot or calculate something it in the loop.

Ineluctable answered 20/10, 2016 at 13:41 Comment(0)
M
6

I have (re)implemented some features of knitr independently from @Yihui based on brew in my pander package that could help with such (and similar) issues if you do not want to run brew before knitting. Quick demo:

> Pandoc.brew(text = "# Demonstrating a nice loop
+ <% for (i in 1:5) { %>
+ ## This is a header for <%=i%>
+ #' This is a comment for <%=i%>
+ <% } %>")

# Demonstrating a nice loop

## This is a header for _1_
#' This is a comment for _1_

## This is a header for _2_
#' This is a comment for _2_

## This is a header for _3_
#' This is a comment for _3_

## This is a header for _4_
#' This is a comment for _4_

## This is a header for _5_
#' This is a comment for _5_

Please note that you could also pass a file to Pandoc.brew (no need to use such troublesome setup with the text argument with real-life problems), and that you could also use <% ... %> tags for e.g. conditionals (like showing or not rendering part of a report). And most importantly: there is a huge difference between <% ... %> (unprocessed R commands) and <%= ... %> (results are processed by pander) tags. The latter means that all returned R objects are transformed to Pandoc's markdown, e.g.:

> Pandoc.brew(text = "# Demonstrating a conditional
+ <% for (i in 1:5) { %>
+ ## This is a header for <%=i%>
+ <% if (i == 3) { %>
+ Hey, that's **almost** <%=pi%>, that's between <%=3:4%>! Wanna fit a model to _celebrate_?
+ <%= lm(mpg ~ hp, mtcars) %>
+ <% }} %>")
# Demonstrating a conditional

## This is a header for _1_

## This is a header for _2_

## This is a header for _3_

Hey, that's **almost** _3.142_, that's between _3_ and _4_! Wanna fit a model to _celebrate_?

--------------------------------------------------------------
     &nbsp;        Estimate   Std. Error   t value   Pr(>|t|) 
----------------- ---------- ------------ --------- ----------
     **hp**        -0.06823    0.01012     -6.742   1.788e-07 

 **(Intercept)**     30.1       1.634       18.42   6.643e-18 
--------------------------------------------------------------

Table: Fitting linear model: mpg ~ hp

## This is a header for _4_

## This is a header for _5_
Mumford answered 18/6, 2013 at 21:45 Comment(1)
thanks for the suggestion. I was hoping to avoid using too many explicit tags in the R code, but it's good to know there is a work around.Ranch

© 2022 - 2024 — McMap. All rights reserved.