「PDFのコンパイル」の代わりにknit()
/knit2pdf()
を使用した場合の(望ましくない)副作用は何ですか1 RStudioのボタン?
knitr
のほとんどのユーザーは、RStudioでドキュメントを作成し、[PDFのコンパイル]/[HTMLのニット]ボタンを使用してドキュメントをコンパイルするようです。これはほとんどの場合スムーズに機能しますが、コンパイルボタンを使用して達成できない特別な要件がときどきあります。これらの場合、解決策は通常、knit()
/knit2pdf()
/rmarkdown::render()
(または類似の関数)を直接呼び出すことです。
いくつかの例:
「PDFのコンパイル」ボタンの代わりにknit2pdf()
を使用すると、通常、このような質問に対する簡単な解決策が提供されます。ただし、これには代償が伴います。「PDFのコンパイル」がドキュメントを処理するという根本的な違いがあります 別のプロセスと環境で に対して、knit2pdf()
とその仲間は処理しません。
これには影響があり、問題はこれらの影響のすべてが明白ではないということです。knit()
がグローバルからオブジェクトを使用するという事実を取ります例として環境(「PDFのコンパイル」にはありません)。これは明白であり、上記の2番目の例のような場合には望ましい動作ですが、knit()
を使用すると、予期しない結果になります例1と3のような問題を克服する。
さらに、さらに微妙な違いがあります。
「PDFのコンパイル」の代わりにknit2pdf()
を使用するためのアドバイスを読み書きするときはいつでも「正しいと思いますが、ユーザーは結果を理解する必要があります…」。
したがって、ここでの質問は次のとおりです。
RStudioの[PDFのコンパイル]ボタンの代わりに
knit()
/knit2pdf()
を使用した場合の(望ましくない)副作用は何ですか?
この質問に対する包括的な(コミュニティwiki?)回答があった場合、knit2pdf()
の使用を提案する将来の回答にリンクすることができます。
この問題には数十の関連する質問があります。ただし、RStudioボタンの動作を(多かれ少なかれ)再現するためのコードのみを提案するか、起こり得る落とし穴について言及せずに「基本的に」何が起こるかを説明します。他は非常によく似た質問のように見えますが、(非常に)特別なケースであることが判明しました。いくつかの例:
Sys.sleep(30)
も "Compile PDF"ログ も洞察に富んでいない(両方のヒントが同じものを指している)。この質問は、回答の一部となるべき多くの問題を引き起こしたと思います。しかし、私が知らない多くの側面があるかもしれません。それが私がこの質問に自己回答することに消極的である理由です(だれも答えない場合は試すかもしれませんが)。
おそらく、回答は3つの主要なポイントをカバーする必要があります。
knit()
が呼び出し環境のオブジェクトを使用するという事実(デフォルト:envir = parent.frame()
)と再現性への影響。 knit()
がドキュメントの外部からオブジェクトを使用できないようにする問題に取り組みました この答え (2番目の箇条書き)。私はこの問題についての正しい見方を知りません。 「 'Compile PDF' +の影響を押したときに何が起こるか」と「knit()
+の影響を使ったときに何が起こるか」の両方が、この問題に取り組む良いアプローチだと思います。
1 同じことが、RMDドキュメントを作成するときの「Knit HTML」ボタンにも当てはまります。
まず、「HTMLをニット」ボタンは別の話なので、「PDFをコンパイル」ボタンに範囲を限定すると、この質問の方が答えやすいと思います。 「Compile PDF」はRnwドキュメント(R + LaTeX、またはSweaveと考える)専用です。
私はあなたが提案した3つのポイントに従ってあなたの質問に答えます:
現在、RStudioは常に新しいRセッションを起動してRnwドキュメントをコンパイルし、最初に作業ディレクトリをRnwファイルのディレクトリに変更します。次のようなシェルスクリプトとしてプロセスを想像できます。
cd path/to/your-Rnw-directory
Rscript -e "library(knitr); knit('your.Rnw')"
pdflatex your.tex
knitrパッケージは常に添付され、pdflatex
は他のLaTeXエンジンである可能性があることに注意してください(SweaveドキュメントのRStudio構成によっては、xelatex
など)。現在のRセッションでそれを複製したい場合は、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()
内)。
Rnwドキュメントは常に新しいRセッションでコンパイルされるため、現在のRセッションではオブジェクトを使用しません。これは、現在のRセッションでknitr::knit()
のenvir
引数を介してのみ複製することは困難です。特に、knitr::knit(envir = new.env())
は新しい環境ですが、デフォルトの親環境new.env()
(通常はparent.frame()
)があるため、globalenv()
は使用できません。 knitr::knit(envir = emptyenv())
も使用できません。これは「クリーンすぎる」ため、R baseパッケージのオブジェクトでも問題が発生するためです。 「PDFのコンパイル」ボタンの機能を複製する唯一の信頼できる方法は、system2("Rscript", c("-e", shQuote("library(knitr); knit('your.Rnw')"))
で私が言ったことです。この場合、knit()
は新しいRセッションのglobalenv()
を使用します。
RStudioがrepos
オプションに対して何を行うかについては、完全にはわかりません。このオプションが設定されていない場合は、おそらくこのオプションが自動的に背後で設定されます。これは比較的小さな問題だと思います。 .Rprofile
で設定できます。RStudioはCRANミラー設定を尊重する必要があると思います。
ユーザーは、Rnwドキュメント(またはR Markdownドキュメント)が現在のRセッションでコンパイルされない理由を常に尋ねてきました。私たちにとって、それは基本的に次の結果のどれがより意外であるか望ましくない結果であるかを要約します:
要約すると、私は思う:
新しいRセッションで編み物を行うと、再現性が向上します。
現在のRセッションで編成する方が便利な場合があります(たとえば、現在のセッションで別の一時的なRオブジェクトを使用して編成しようとした場合)。特にプログラムでPDFレポートを生成している場合など、現在のRセッションで編成する必要がある場合もあります。たとえば、(for)ループを使用して一連のレポートを生成します。方法はありません。これは、[PDFをコンパイル]ボタンを使用してのみ実現できます(ボタンは、ほとんどの場合、単一のRnwドキュメント専用です)。
ところで、私が上で言ったことはKnitまたはKnit HTMLボタンにも適用できると思いますが、基本的な機能はrmarkdown::render()
ではなくknitr::knit()
です。