Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plot created outside of knit function somehow sneaks into knit_child #2166

Closed
3 tasks done
niklaswillrich opened this issue Sep 2, 2022 · 9 comments
Closed
3 tasks done
Labels
bug Bugs

Comments

@niklaswillrich
Copy link

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

  • I have fully read the issue guide at https://yihui.org/issue/.
  • 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.
  • 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.

@yihui
Copy link
Owner

yihui commented Sep 2, 2022

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

@cderv
Copy link
Collaborator

cderv commented Sep 2, 2022

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 ?

knitr/R/block.R

Lines 201 to 208 in 907184f

# open a device to record plots if not using a global device or no device is
# open, and close this device if we don't want to use a global device
if (!opts_knit$get('global.device') || is.null(dev.list())) {
chunk_device(options, keep != 'none', tmp.fig)
dv = dev.cur()
if (!opts_knit$get('global.device')) on.exit(dev.off(dv), add = TRUE)
showtext(options) # showtext support
}

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 cderv added the bug Bugs label Sep 2, 2022
@yihui
Copy link
Owner

yihui commented Sep 2, 2022

@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())?

@niklaswillrich
Copy link
Author

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!

@cderv
Copy link
Collaborator

cderv commented Sep 3, 2022

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.

@niklaswillrich
Copy link
Author

@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
Copy link
Author

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

@yihui yihui closed this as completed in ff3d767 Oct 4, 2022
@yihui
Copy link
Owner

yihui commented Oct 4, 2022

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

remotes::install_github('yihui/knitr')

Thanks!

yihui added a commit that referenced this issue Nov 10, 2022
…usly

otherwise it can cause a problem here: https://github.com/cran/monitoR/blob/e07ae7423dbfd08eeaf1a5916060103761391e35/R/Methods-plot.R#L139 because dev.set(1) (i.e. set the null device) will make dev.list() a vector of length > 1 (although I don't understand why), and `if (dev.list() == 2)` will throw an error "the condition has length > 1"
@github-actions
Copy link

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 github-actions bot locked as resolved and limited conversation to collaborators Apr 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Bugs
Projects
None yet
Development

No branches or pull requests

3 participants