在for循环中生成Markdown注释

17
我希望能够使用knitr根据一个包含for循环的R脚本生成HTML报告。我想从for循环内的注释中生成markdown注释,但我不确定是否可能。
这里是一个简单的例子,在test.R文件中:
for (i in 1:5) {
    ## This is a heading for `i`
    #' This is a comment for `i`
    print(i)    
}

然后我使用spin函数生成一个Rmd文件:

spin('test.R')

然而,生成的Rmd文件长这个样子。

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

R代码块中的Markdown注释不会被编译为HTML。这是否可能?

谢谢, Peter


1
听起来你想在转换为Rmd之前运行一些R代码,而我理解的是spin(然后是knit)是以相反的方式进行的。我认为brew模板可能会有所帮助。 - baptiste
1
我觉得你真正想说的是_roxygen_注释,而不是_Markdown_注释。正如@baptiste所提到的,brew对于这种任务(从循环中生成文本)更加复杂。 - Yihui Xie
@Yihui,你是正确的。R文件包含roxygen注释,我希望在运行spin后它们将被转换为Markdown注释。 - pmichaels
@baptiste,谢谢你的建议,我会去看看brew。 - pmichaels
3个回答

17

我认为你可以在knitr中使用代码块选项results='asis'获得想要的结果。你可以在R脚本中在“#+”后指定该选项,以便传递给spin(但与@daroczig提出的有趣的brew解决方案相比,代码看起来不那么干净):

#+ 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)    
}

如果这是一个名为test.R的脚本文件,你在其中执行spin("test.R")命令,则生成的md文件将如下所示:
## 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

这使我能够将注释放入输出中,但是这些注释没有使用 Markdown 标记进行格式化。 - pmichaels
你是指使用 Markdown 标记格式化的注释吗?你是在寻找 HTML 注释吗?如果是,你可以按照同样的方式来做,参考我的编辑示例。 - Gilles San Martin
4
我需要在print(i)后再加上一个cat('\n'),这样才能将标题2到5渲染为标题。 - jbaums

9

我用过的一个解决方案是由如何在R中创建同时包含代码块和文本的循环提供。通过使用Bothresults='asis'以及在每个循环结尾处加上\n前面的两个空格。

示例:

没有两个空格的情况

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

输出(html):

在这里输入图片描述

如您所见,注释和标题混在一起了。

解决方法: 加两个空格:循环结束时cat(" \n")

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

在此输入图片描述

注意:cat(" \n") 需要放在循环的最后,即使你在循环中绘图或计算也无效。


6

基于brew,我在我的pander软件包中独立实现了一些knitr的功能,如果您不想在knit之前运行brew,这些功能可以帮助您解决类似的问题。快速演示:

> 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_

请注意,您也可以将文件传递给 Pandoc.brew(在面临真实问题时,无需使用带有text参数的麻烦设置),并且您还可以使用<% ... %>标记进行条件控制(例如显示或不呈现报告的部分)。最重要的是: <% ... %>(未处理的 R 命令)和 <%= ... %>(结果由pander处理)标记之间存在巨大差异。后者意味着所有返回的 R 对象都将转换为 Pandoc 的 markdown,例如:
> 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_

谢谢您的建议。我希望在R代码中避免使用太多显式标签,但知道有一个解决方法还是很好的。 - pmichaels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接