knitr icon indicating copy to clipboard operation
knitr copied to clipboard

Plot created outside of knit function somehow sneaks into knit_child

Open niklaswillrich opened this issue 3 years ago • 7 comments

I have a problem where knitting a child document according to the recommendation under https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html results in some weird behaviour. A plot which was printed in the global environment is inserted in the output of knitr.

This has happened in a more complex setup where I was rendering Rmarkdown files with Child-Documents. I have tried to create a minimal reproducible example as follows:

I have a main.Rmd with the following syntax:

```{r, results = "asis"}
print("I am main.")
res <- knitr::knit_child("child.Rmd")
cat(res, sep = '\n')
```

and I have a child.Rmd

```{r}
print("I am the child.")
```

I then run

plot(1:10)
knitr::knit("main.Rmd")

I get the following main.md as output:



```r
print("I am main.")
```

[1] "I am main."

```r
res <- knitr::knit_child("child.Rmd")
```

```
## 
## 
## processing file: test_knitr/child.Rmd
```


  |                                                             
  |                                                       |   0%
  |                                                             
  |.......................................................| 100%
label: unnamed-chunk-2

```r
cat(res, sep = '\n')
```

![plot of chunk unnamed-chunk-1](figure/unnamed-chunk-1-1.png)

```r
print("I am the child.")
```

```
## [1] "I am the child."
```

The plot which was created outside of the knit-function is now inside the document. I could reproduce this problem for different R versions and different machines.

Thanks!

P.S.: I am happy to supplement additional infos etc. if you need it.

Session info:

R version 4.2.1 (2022-06-23 ucrt) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19044)

Locale: LC_COLLATE=German_Germany.utf8 LC_CTYPE=German_Germany.utf8
LC_MONETARY=German_Germany.utf8 LC_NUMERIC=C
LC_TIME=German_Germany.utf8

Package version: evaluate_0.16 glue_1.6.2 graphics_4.2.1 grDevices_4.2.1 highr_0.9 knitr_1.40.1
magrittr_2.0.3 methods_4.2.1 stats_4.2.1
stringi_1.7.8 stringr_1.4.1 tools_4.2.1
utils_4.2.1 xfun_0.32 yaml_2.3.5


By filing an issue to this repo, I promise that

  • [x] I have fully read the issue guide at https://yihui.org/issue/.
  • [x] I have provided the necessary information about my issue.
    • If I'm asking a question, I have already asked it on Stack Overflow or RStudio Community, waited for at least 24 hours, and included a link to my question there.
    • If I'm filing a bug report, I have included a minimal, self-contained, and reproducible example, and have also included xfun::session_info('knitr'). I have upgraded all my packages to their latest versions (e.g., R, RStudio, and R packages), and also tried the development version: remotes::install_github('yihui/knitr').
    • If I have posted the same issue elsewhere, I have also mentioned it in this issue.
  • [x] I have learned the Github Markdown syntax, and formatted my issue correctly.

I understand that my issue may be closed if I don't fulfill my promises.

niklaswillrich avatar Sep 02 '22 11:09 niklaswillrich

This sounds weird. @cderv Are you able to reproduce the problem?

yihui avatar Sep 02 '22 19:09 yihui

Hi,

yes I am able to reproduce. See Details below

Details
> plot(1:10)
> knitr::knit("test.Rmd")


processing file: test.Rmd
  |...............................................................................                                                                               |  50%
  ordinary text without R code

  |..............................................................................................................................................................| 100%
label: unnamed-chunk-1 (with options) 
List of 1
 $ results: chr "asis"


output file: test.md

[1] "test.md"
> xfun::file_string("test.md")
---
title: "Untitled"
output: html_document
---


```r
print("I am main.")
```

[1] "I am main."

```r
res <- knitr::knit_child("child.Rmd", quiet = TRUE)
cat(res, sep = '\n')
```

![plot of chunk unnamed-chunk-1](figure/unnamed-chunk-1-1.png)

```r
print("I am the child.")
```

```
## [1] "I am the child."
```

Closing the graphic device before knitting fix the issue. So doing this fix it:

plot(1:10)
dev.off() # adding this fix the issue - no plot included as image
knitr::knit("test.Rmd")
Details
> plot(1:10)
> dev.off()
null device 
          1 
> knitr::knit("test.Rmd")


processing file: test.Rmd
  |...............................................................................                                                                               |  50%
  ordinary text without R code

  |..............................................................................................................................................................| 100%
label: unnamed-chunk-1 (with options) 
List of 1
 $ results: chr "asis"


output file: test.md

[1] "test.md"
> xfun::file_string("test.md")
---
title: "Untitled"
output: html_document
---


```r
print("I am main.")
```

[1] "I am main."

```r
res <- knitr::knit_child("child.Rmd", quiet = TRUE)
cat(res, sep = '\n')
```

```r
print("I am the child.")
```

```
## [1] "I am the child."
```

it seems knitr will indeed use an existing open one right ? https://github.com/yihui/knitr/blob/907184f82489488ab8fd3619aa15b9822bf96067/R/block.R#L201-L208

It could be link to this. It is also happening only when using knit_child() is used, and image is included right before the knit_child content.

---
title: "Untitled"
output: html_document
---

```{r}
print("I am main.")
res <- knitr::knit_child("child.Rmd", quiet = TRUE)
res
```

will show us this in knitr

```r
res <- knitr::knit_child("child.Rmd", quiet = TRUE)
res
```

![plot of chunk unnamed-chunk-1](figure/unnamed-chunk-1-1.png)

```
## [1] "\n\n```r\nprint(\"I am the child.\")\n```\n\n```\n## [1] \"I am the child.\"\n```"
```

So it does not seem to be inside res which is knit_child result. We should check what knitting_child can trigger.

Can't you reproduce ? Is this a windows issue ?

cderv avatar Sep 02 '22 20:09 cderv

@cderv I didn't try to reproduce (just asking you for help instead).

I don't remember why I wanted to avoid opening a new device when an existing device is open (i.e., dev.list() is not NULL). Perhaps I should remove this condition.

@niklaswillrich Would it be much trouble for you to close the device after the plot (i.e., plot() then dev.off())?

yihui avatar Sep 02 '22 22:09 yihui

If I call dev.off() after plot() the figure is not inserted anymore.

The main.md now looks like this:



```r
print("I am main.")
```

[1] "I am main."

```r
res <- knitr::knit_child("child.Rmd")
```

```
## 
## 
## processing file: test_knitr/child.Rmd
```


  |                                                             
  |                                                       |   0%
  |                                                             
  |.......................................................| 100%
label: unnamed-chunk-2

```r
cat(res, sep = '\n')
```

```r
print("I am the child.")
```

```
## [1] "I am the child."
```

I will force dev.off() before all the rendering of Rmarkdown in my original project as a workaround for now and wait for a possible bug fix.

Still happy to test stuff provide further information.

Thanks for the quick reply and help!

niklaswillrich avatar Sep 03 '22 05:09 niklaswillrich

I didn't try to reproduce (just asking you for help instead).

@yihui Ok great no problem. I'll look closer to this - I want to understand. That is an unexpected behavior.

I will force dev.off() before all the rendering of Rmarkdown

@niklaswillrich is this happening with rmarkdown::render too ?

The example shared only used knitr to render the Rmd to md and not rmarkdown completely.

cderv avatar Sep 03 '22 06:09 cderv

@cderv yes, this is happening with rmarkdown::render too.

If you replace knitr::knit("main.Rmd") with rmarkdown::render("main.Rmd") the plot is still shown inside the output.

niklaswillrich avatar Sep 03 '22 09:09 niklaswillrich

Just as a clarification: dev.off() solves the problem for rmarkdown::render too.

niklaswillrich avatar Sep 03 '22 10:09 niklaswillrich

I have finally figured out and fixed this weird problem. You can install the development version via

remotes::install_github('yihui/knitr')

Thanks!

yihui avatar Oct 04 '22 20:10 yihui

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.

github-actions[bot] avatar Apr 19 '23 05:04 github-actions[bot]