I have a markdown file that loops through a bunch of datasets, make figures and tables from them and saves as one html file. This file is called internally from a function the user runs.
If the user runs the main function from an r script or in the console it works. If they knit their whole markdown file it works. The problem comes up when the user tries to run the main function from their own markdown file. If they run the chunk that calls the function in the markdown script, the tables don't get printed in the intended HTML file, but they get printed to the user's markdown HTML file.
This only happens if the external markdown file is printing the tables in a loop, and unfortunately, I can't figure out how to avoid the loop.
Here is a toy example that recreates the problem.
user_markdown.Rmd:
---
title: "User's markdown"
author: ""
date: '`r Sys.Date()`'
output: html_document
---
```{r}
rmarkdown::render("test.rmd")
```
test.Rmd:
---
title: "test"
author: ""
date: "`r Sys.Date()`"
output: html_document
---
```{r}
df1<-data.frame(x=rnorm(10),y=rnorm(10))
for(i in 1) {
print(knitr::kable(df1))
}
```
Running the chunk in the user's markdown (as opposed to knitting the whole thing or running in console), causes the table not to print to test.html as desired. I've tried using {kableExtra}
or {flextable}
for the table, but nothing works.
Printing directly without using knitr::kable()
, i.e. print(df1)
, works but loses the desired formatting. Is there a way to make the table print from inside a loop, with formatting, if the user runs their code chunk in markdown? I'm running R 4.5.0 in RStudio.
knitr treats outputs differently based on calling context. When you wrap your code within a for-loop (a control structure), knitr sees a dynamic output (vs. static output of a direct chunk statement). knitr's print method dispatch is different for each of these scenarios. In your example, you have triple nesting: interactive chunk -> render -> loop. This "overwhelms" knitr's context detection, causing it to fall back to parent document (user_markdown.html) instead of child (test.html).
We can use cat()
instead of print()
. It write to the currently active file/connection regardless of the execution method.
---
title: "Test Document"
author: ""
date: "`r Sys.Date()`"
output: html_document
---
```{r, results='asis'}
set.seed(42)
df1 <- data.frame(x = rnorm(10), y = rnorm(10))
for(i in 1:2) {
tbl <- knitr::kable(df1, format = "markdown")
cat(paste(tbl, collapse = "\n"))
cat("\n\n")
}
```