区别:“编译PDF" RStudio中的按钮vs. knit()和knit2pdf() [英] Difference: "Compile PDF" button in RStudio vs. knit() and knit2pdf()

查看:163
本文介绍了区别:“编译PDF" RStudio中的按钮vs. knit()和knit2pdf()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在RStudio中使用knit()/knit2pdf()而不是"Compile PDF" 1 按钮有哪些(可能是不需要的)副作用?

What are the (possibly unwanted) side-effects of using knit()/knit2pdf() instead of the "Compile PDF"1 button in RStudio?

knitr的大多数用户似乎在RStudio中编写他们的文档,并使用编译PDF"/编织HTML"按钮来编译文档.这在大多数情况下都可以顺利进行,但有时会有一些特殊要求无法使用编译"按钮来实现.在这种情况下,解决方案通常是直接调用knit()/knit2pdf()/rmarkdown::render()(或类似函数).

Most users of knitr seem to write their documents in RStudio and compile the documents using the "Compile PDF" / "Knit HTML" button. This works smoothly most of the time, but every once a while there are special requirements that cannot be achieved using the compile button. In these cases, the solution is usually to call knit()/knit2pdf()/rmarkdown::render() (or similar functions) directly.

一些例子:

  • How to knit/Sweave to a different file name?
  • Is there a way to knitr markdown straight out of your workspace using RStudio?
  • Insert date in filename while knitting document using RStudio Knit button

使用knit2pdf()代替编译PDF"按钮通常可以为此类问题提供简单的解决方案.但是,这是有代价的:编译PDF"处理文档

Using knit2pdf() instead of the "Compile PDF" button usually offers a simple solution to such questions. However, this comes at a price: There is the fundamental difference that "Compile PDF" processes the document in a separate process and environment whereas knit2pdf() and friends don't.

这具有含义,而问题在于,并非所有这些含义都是显而易见的.knit()使用全局环境中的对象(而"Compile PDF"没有)为事实的事实.例子.在上面的第二个示例这样的情况下,这可能是显而易见的并且是预期的行为,但是当使用knit()克服示例1和3中的问题时,这是意外的结果.

This has implications and the problem is that not all of these implications are obvious. Take the fact that knit() uses objects from the global environment (whereas "Compile PDF" does not) as an example. This might be obvious and the desired behavior in cases like the second example above, but it is an unexpected consequence when knit() is used to overcome problems like in example 1 and 3.

此外,还有更多细微差别:

Moreover, there are more subtle differences:

  • The working directory might not be set as expected.
  • Packages need to be loaded.
  • Some options that are usually set by RStudio may have unexpected values.

每当我读/写使用knit2pdf()而不是"Compile PDF"的建议时,我认为正确,但用户应了解后果……" .

Whenever I read/write the advice to use knit2pdf() instead of "Compile PDF", I think "correct, but the user should understand the consequences …".

因此,这里的问题是:

在RStudio中使用knit()/knit2pdf()而不是"Compile PDF"按钮,有哪些副作用(可能是不需要的)?

What are the (possibly unwanted) side-effects of using knit()/knit2pdf() instead of the "Compile PDF" button in RStudio?

如果对此问题有一个全面的答案(社区Wiki?),可以在以后的答案中使用knit2pdf()将其链接起来.

If there was a comprehensive (community wiki?) answer to this question, it could be linked in future answers that suggest using knit2pdf().

与此相关的问题有数十个.但是,他们要么只提出代码来(或多或少)再现RStudio按钮的行为,要么解释基本"发生的情况,而没有提及可能的陷阱.其他人看起来像是非常相似的问题,但事实证明它是(非常)特殊的情况.一些例子:

There are dozens of related questions to this one. However, they either propose only code to (more or less) reproduce the behavior of the RStudio button or they explain what "basically" happens without mentioning the possible pitfalls. Others look like being very similar questions but turn out to be a (very) special case of it. Some examples:

  • Knit2html not replicating functionality of Knit HTML button in R Studio: Caching issue.
  • HTML outputs are different between using knitr in Rstudio & knit2html in command line: Markdown versions.
  • How to convert R Markdown to HTML? I.e., What does "Knit HTML" do in Rstudio 0.96?: Rather superficial answer by Yihui (explains what "basically" happens) and some options how to reproduce the behavior of the RStudio button. Neither the suggested Sys.sleep(30) nor the "Compile PDF" log are insightful (both hints point to the same thing).
  • What does "Knit HTML" do in Rstudio 0.98?: Reproduce behavior of button.

我认为这个问题提出了许多应作为答案一部分的问题.但是,可能还有许多我不知道的方面,这就是为什么我不愿意自行回答这个问题的原因(尽管如果没有人回答,我可能会尝试).

I think this question raised many of the issues that should be part of an answer. However, there might be many more aspects I don't know about which is the reason why I am reluctant to self-answer this question (though I might try if nobody answers).

答案可能涵盖三个要点:

Probably, an answer should cover three main points:

  • 新会话与当前会话的问题(全局选项,工作目录,已加载的软件包,...).
  • 第一点的结果:knit()使用调用环境中的对象的事实(默认值:envir = parent.frame())及其对再现性的影响.我试图解决防止knit()此答案中使用文档外部的对象的问题(第二个要点)
  • RStudio偷偷做的事情……
    • …在开始交互式会话时(示例)->在单击编译PDF"时不可用
    • …当点击编译PDF"时(除了新会话,工作目录设置为已处理文件之外,还有其他特殊之处吗?)
    • The new session vs. current session issue (global options, working directory, loaded packages, …).
    • A consequence of the first point: The fact that knit() uses objects from the calling environment (default: envir = parent.frame()) and implications for reproducibility. I tried to tackle the issue of preventing knit() from using objects from outside the document in this answer (second bullet point).
    • Things RStudio secretly does …
      • … when starting an interactive session (example) --> Not available when hitting "Compile PDF"
      • … when hitting "Compile PDF" (anything special besides the new session with the working directory set to the file processed?)

      对于该问题的正确观点,我不确定.我认为,当我点击'编译PDF'+含义时会发生什么"以及当我使用knit() +含义时会发生什么"都是解决这个问题的好方法.

      I am not sure about the right perspective on the issue. I think both, "What happens when I hit 'Compile PDF' + implications" as well as "What happens when I use knit() + implications" is a good approach to tackle the question.

      1 编写RMD文档时,编织HTML"按钮也是如此.

      1 The same applies to the "Knit HTML" button when writing RMD documents.

      推荐答案

      首先,如果将范围限制为编译PDF"按钮,我认为这个问题更容易回答,因为编织HTML"按钮是一个不同的故事. 编译PDF"仅适用于Rnw文档(R + LaTeX或Think Sweave).

      First of all, I think this question is easier to answer if you limit the scope to the "Compile PDF" button, because the "Knit HTML" button is a different story. "Compile PDF" is only for Rnw documents (R + LaTeX, or think Sweave).

      我将按照您提出的三点回答您的问题:

      I'll answer your question following the three points you suggested:

      1. 当前,RStudio总是启动一个新的R会话来编译Rnw文档,然后首先将工作目录更改为Rnw文件的目录.您可以将进程想象为一个shell脚本,如下所示:

      1. Currently RStudio always launch a new R session to compile Rnw documents, and first changes the working directory to the directory of the Rnw file. You can imagine the process as a shell script like this:

      cd path/to/your-Rnw-directory
      Rscript -e "library(knitr); knit('your.Rnw')"
      pdflatex your.tex
      

      请注意,始终会附加 knitr 软件包,并且pdflatex可能是其他LaTeX引擎(取决于Sweave文档的RStudio配置,例如xelatex).如果要在当前的R会话中复制它,则可以在R:中重写脚本:

      Note that the knitr package is always attached, and pdflatex might be other LaTeX engines (depending on your RStudio configurations for Sweave documents, e.g., xelatex). If you want to replicate it in your current R session, you may rewrite the script in R:

      owd = setwd("path/to/your-Rnw-directory")
      system2("Rscript", c("-e", shQuote("library(knitr); knit('your.Rnw')"))
      system2("pdflatex", "your.tex")
      setwd(owd)
      

      并不像knitr::knit('path/to/your.Rnw')那样简单,在这种情况下,工作目录不会自动更改,并且一切都在当前的R会话中执行(默认情况下在globalenv()中).

      which is not as simple as knitr::knit('path/to/your.Rnw'), in which case the working directory is not automatically changed, and everything is executed in the current R session (in the globalenv() by default).

      由于Rnw文档总是在新的R会话中编译,因此它不会在当前R会话中使用任何对象.仅通过当前R会话中的knitr::knit()envir参数很难复制.特别是,您不能使用knitr::knit(envir = new.env()),因为尽管new.env()是一个新环境,但它具有默认的父环境parent.frame(),通常是globalenv().您也不能使用knitr::knit(envir = emptyenv()),因为它太干净了",即使在R base 包中,您也将无法使用对象.复制编译PDF"按钮的唯一可靠方法是我在1:system2("Rscript", c("-e", shQuote("library(knitr); knit('your.Rnw')"))中所说的,在这种情况下,knit()使用新R会话的globalenv().

      Because the Rnw document is always compiled in a new R session, it won't use any objects in your current R session. This is hard to replicate only through the envir argument of knitr::knit() in the current R session. In particular, you cannot use knitr::knit(envir = new.env()) because although new.env() is a new environment, it has a default parent environment parent.frame(), which is typically the globalenv(); you cannot use knitr::knit(envir = emptyenv()), either, because it is "too clean", and you will have trouble with objects even in the R base package. The only reliable way to replicate what the "Compile PDF" button does is what I said in 1: system2("Rscript", c("-e", shQuote("library(knitr); knit('your.Rnw')")), in which case knit() uses the globalenv() of a new R session.

      我不确定RStudio对repos选项的作用.如果未设置此选项,则可能会在后台自动设置该选项.我认为这是一个相对较小的问题.您可以在.Rprofile中进行设置,我认为RStudio应该尊重您的CRAN镜像设置.

      I'm not entirely sure about what RStudio does for the repos option. It probably automatically sets this option behind the scenes if it is not set. I think this is a relatively minor issue. You can set it in your .Rprofile, and I think RStudio should respect your CRAN mirror setting.

      用户一直在问为什么在当前R会话中未编译Rnw文档(或R Markdown文档).对我们来说,基本上可以归结为以下哪些后果更令人惊讶或不期望:

      Users have always been asking why the Rnw document (or R Markdown documents) are not compiled in the current R session. To us, it basically boils down to which of the following consequences is more surprising or undesired:

      1. 如果我们在当前的R会话中编织文档,则不能保证可以在另一个R会话中复制您的结果(例如,下次打开RStudio或合作者在其计算机上打开RStudio).
      2. 如果我们在新的R会话中编织文档,用户可能会惊讶地发现找不到对象(当他们在R控制台中键入对象名称时,他们可以看到它们).这可能令人惊讶,但它同时也是一个很好的早期提醒,下次您的文档可能无法使用.

      总而言之,我认为:

      • 在新的R会话中进行编织对于重现性更好;

      • Knitting in a new R session is better for reproducibilty;

      在当前R会话中进行编织有时会更方便(例如,您尝试在当前会话中与其他临时R对象进行编织).有时您还必须在当前的R会话中进行编织,尤其是在以编程方式生成PDF报告时,例如,使用(for)循环来生成一系列报告.您无法仅通过编译PDF"按钮(该按钮主要仅用于单个Rnw文档)来实现此目的.

      Knitting in the current R session is sometimes more convenient (e.g., you try to knit with different temporary R objects in the current session). Sometimes you also have to knit in the current R session, especially when you are generating PDF reports programmatically, e.g., you use a (for) loop to generate a series of reports. There is no way that you can achieve this only through the "Compile PDF" button (the button is mostly only for a single Rnw document).

      顺便说一句,我想我上面所说的内容也可以适用于Knit或Knit HTML按钮,但是基本功能是rmarkdown::render()而不是knitr::knit().

      BTW, I think what I said above can also apply to the Knit or Knit HTML buttons, but the underlying function is rmarkdown::render() instead of knitr::knit().

      这篇关于区别:“编译PDF" RStudio中的按钮vs. knit()和knit2pdf()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆