使用循环在rmarkdown中生成文本部分

ldioqlga  于 2023-03-20  发布在  其他
关注(0)|答案(4)|浏览(162)

我需要生成一个由几个部分组成的报表,所有部分看起来都很相似,只是数据有一些不同。部分的数量也取决于数据。我最终想要的是这样的:

```{r}
  section_names = c("A","B","C")
  section_data = c(13,14,16)

some looping mechanism here with variable i

This is section r section_names[i]

This section's data is r section_data[i]

#more things go here for the section

#end of loop should go here


结果应该是一个单独的html/文档,所有部分一个接一个。
你能告诉我用循环生成这样一个Rmd文件的方法吗?
理想情况下,我希望在PHP中看到类似的内容:

<$php for(i=0;i<10;i++) { ?>

some html template + code chunks here

<$php } ?>

xqnpmsa8

xqnpmsa81#

这个问题类似于that one,虽然它是基于LateX/RNW的。此外,this answer演示了如何动态生成一个rmarkdown文档。但是,这两个问题都不是这个问题的完全重复。
基本上,有两个心理步骤要采取:

  • 计算出每个部分所需的markdown标记。这可以是沿着于
## This is section <section_name>
Section data is `<section_data>`.
Additional section text is: <section_text>.
  • 编写生成此标记的R代码,用适当的值替换占位符。

对于第2步,使用sprintf是合并静态和动态文本的自然选择。不要忘记使用chunk optionsresults = "asis"来防止knitr向输出添加格式,使用cat(而不是print)来防止R添加额外的东西,如引号和元素编号。
为了清晰起见,我稍微更改了输入数据结构(使用data.frame代替独立向量section_namessection_data)。

```{r echo = FALSE, results = "asis"}
input <- data.frame(
  name = LETTERS[1:4],
  data = runif(n = 4),
  text = replicate(4, paste(sample(x = LETTERS, size = 100, replace = TRUE), collapse = "")),
  stringsAsFactors = FALSE)

template <- "## This is section %s
Section data is `%0.2f`.
Additional section text is: %s.

" # dont't forget the newline

for (i in seq(nrow(input))) {
  current <- input[i, ]
  cat(sprintf(template, current$name, current$data, current$text))
}

## 输出:

### 这是A部分

节数据为`0.83`。其他节文本为:普夫茨克齐夫内马奥普特维克尔贝斯克姆姆沃德夫热斯普林罗特维格内罗夫克齐夫姆姆姆普沃格格格里姆考奥姆维克斯克姆姆姆姆姆赫尼维兹普拉普鲁.

### 这是B部分

节数据为`0.49`。其他节文本为:普富蒂加夫斯克斯马 iis 克什克耶夫什基耶夫斯基耶普普什瓦基乌夫克蒂乌斯托伊克什费杰卡伊克克什特鲁德克什基.

### 这是C部分

截面数据为`0.58`。其他截面文本为:预测数据总线控制器VSBPYWCKSFJEARBXXFPAGBTKCWKHPEDGYTNGLVGGJAFZRUMNSDCHKTTMGRFNSUZKFLOUGNWHUBNLVMGDB.

### 这是D部分

节数据为`0.52`。其他节文本为:YQIX具有数量有限的阀门组件,其数量为各种型号的阀门系统,其数量为阀门的长度。
cl25kdpy

cl25kdpy2#

只是分享一下我最终使用的方法。
我为该节编写了一个markdown文件,为主文档中的每个节准备了数据,并循环遍历所有需要的节,每次都使用节Rmd调用knit_child()。

dgtucam1

dgtucam13#

我知道这有点晚了,但是我在代码中使用了这个方法来创建编号部分,效果很好。

for (k in 1:length(listcsv)){ #Begin Loop at pdf file one and continue until all have been completed
subsection <- paste("5", k, sep = ".")}

这使用循环编号(k)来创建子章节编号,然后将其粘贴到章节编号上。2这恰好是在第5节中,但是你可以使用相同的原理来创建无限的章节和子章节。

ddrv8njm

ddrv8njm4#

在@amit的答案上构建一个关于knit_child()使用的示例。根据knitr documentation,可以做一些类似于以下提问的事情:
1.将块的输出设置为as-is
1.在调用knitr_child()之前设置可能在子文档中访问的变量,因为一旦呈现,子文档的环境就与父文档相同。这是我找到的向子文档“传递参数”的唯一方法,但也许有一种更优雅的方法可以做到这一点。
1.在列表中存储knitr_child()输出。
1.使用cat将它们依次打印。
我已经使用Quarto完成了这项工作,但我认为它应该工作得一样,因为knitr是为Rmarkdown而构建的。
一个可重复的小示例:
如果您的子文档child.qmd如下所示:

---
tag: "Child document"
title: "Child document"
---

## `r child_section_title`

This section changes title according to what `child_section_title` value
is in the main markdown document.

您可以在主.qmd文件中呈现多个不同标题的块,执行如下操作:

```{r, results='asis'}
knit_child_with_params <- function(p) {
  child_section_title <- p
  knitr::knit_child(
    "child.qmd",
    envir = environment(),
    quiet = TRUE)
}

# This needs to be declared outside the function
child_section_title <- ""
title_list <- list("Section title 1",
                   "Another title",
                   "Some other thing")

res <- lapply(title_list, knit_child_with_params)

cat(unlist(res), sep = '\n')

如果您打算这样做,请考虑保持子文档块未命名,否则重复的名称将使呈现崩溃。

相关问题