Подтвердить что ты не робот

Разница: кнопка "Скомпилировать PDF" в RStudio vs. knit() и knit2pdf()

TL; DR

Каковы (возможно нежелательные) побочные эффекты использования knit()/knit2pdf() вместо "Compile PDF" 1 кнопка в RStudio?

мотивация

Кажется, что большинство пользователей knitr пишут свои документы в RStudio и компилируют документы, используя кнопку "Compile PDF"/"Knit HTML". Это работает плавно в большинстве случаев, но время от времени существуют особые требования, которые невозможно выполнить с помощью кнопки компиляции. В этих случаях решение, как правило, для вызова knit()/knit2pdf()/rmarkdown::render() (или аналогичные функции) непосредственно.

Некоторые примеры:

Использование knit2pdf() вместо кнопки "Compile PDF" обычно предлагает простое решение таких вопросов. Однако это имеет свою цену: есть принципиальная разница, что "Компилировать PDF" обрабатывает документ в отдельном процессе и среде, тогда как knit2pdf() и друзья этого не делают.

Это имеет значение, и проблема в том, что не все эти последствия очевидны. Возьмем тот факт, что knit() использует объекты из глобальной среды (в отличие от "Compile PDF") в качестве примера. Это может быть очевидным и желаемым поведением в случаях, подобных второму примеру выше, но это неожиданное последствие, когда knit() используется для преодоления проблем, как в примерах 1 и 3.

Кроме того, есть более тонкие различия:

Вопрос и его цель

Всякий раз, когда я читаю/пишу совет использовать knit2pdf() вместо "Compile PDF", я думаю, что "правильно, но пользователь должен понимать последствия…".

Таким образом, вопрос здесь:

Каковы (возможно нежелательные) побочные эффекты использования knit()/knit2pdf() вместо кнопки "Compile PDF" в RStudio?

Если на этот вопрос был исчерпывающий ответ (вики-сообщество?), knit2pdf() можно было бы связать в будущих ответах, предлагающих использовать knit2pdf().

Смежные вопросы

Есть десятки связанных с этим вопросов. Тем не менее, они либо предлагают только код для (более или менее) воспроизведения поведения кнопки RStudio, либо объясняют, что "в основном" происходит, не упоминая возможные подводные камни. Другие выглядят как очень похожие вопросы, но оказываются (очень) особым случаем. Некоторые примеры:

Об ответе

Я думаю, что этот вопрос поднял многие вопросы, которые должны быть частью ответа. Однако, может быть, есть еще много аспектов, о которых я не знаю, из-за чего я не хочу самостоятельно отвечать на этот вопрос (хотя я могу попробовать, если никто не ответит).

Вероятно, ответ должен охватывать три основных момента:

  • Новый сеанс против текущей проблемы сеанса (глобальные параметры, рабочий каталог, загруженные пакеты и т.д.).
  • Следствие из первого пункта: тот факт, что knit() использует объекты из вызывающей среды (по умолчанию: envir = parent.frame()) и последствия для воспроизводимости. В этом ответе я попытался решить проблему предотвращения использования knit() объектов извне документа (второй пункт).
  • Вещи RStudio тайно делает...
    • … При запуске интерактивного сеанса (пример) → Недоступно при нажатии "Компилировать PDF"
    • … При нажатии "Компилировать PDF" (что-нибудь особенное, кроме нового сеанса с рабочим каталогом, в котором установлен файл, обработанный?)

Я не уверен в правильном взгляде на проблему. Я думаю, что "Что происходит, когда я нажимаю" Компилировать PDF "+ последствия", а также "Что происходит, когда я использую knit() + последствия", - это хороший подход к решению этого вопроса.


1 То же самое относится к кнопке "Вязать HTML" при написании документов RMD.

4b9b3361

Ответ 1

Прежде всего, я думаю, что на этот вопрос легче ответить, если вы ограничите область действия кнопкой "Компилировать PDF", потому что кнопка "Вязать HTML" - это отдельная история. "Компилировать PDF" предназначен только для документов Rnw (R + LaTeX, или, кажется, Sweave).

Я отвечу на ваш вопрос, следуя трем пунктам, которые вы предложили:

  1. В настоящее время RStudio всегда запускает новый сеанс R для компиляции документов Rnw и сначала меняет рабочий каталог на каталог файла Rnw. Вы можете представить процесс в виде сценария оболочки следующим образом:

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

    Обратите внимание, что пакет knitr всегда подключен, и pdflatex может быть другими механизмами LaTeX (в зависимости от ваших конфигураций RStudio для документов Sweave, например, 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() по умолчанию в globalenv()).

  2. Поскольку документ Rnw всегда компилируется в новом сеансе R, он не будет использовать никаких объектов в текущем сеансе R. Это трудно повторить только через envir аргумент knitr::knit() в текущей сессии R. В частности, вы не можете использовать knitr::knit(envir = new.env()) потому что хотя new.env() является новой средой, она имеет родительскую среду по умолчанию parent.frame(), которая обычно является globalenv(); вы также не можете использовать knitr::knit(envir = emptyenv()), потому что он "слишком чистый", и у вас будут проблемы с объектами даже в базовом пакете R. Единственный надежный способ воспроизвести действия кнопки "Компилировать PDF" - это то, что я сказал в 1: system2("Rscript", c("-e", shQuote("library(knitr); knit('your.Rnw')")), в этом случае knit() использует globalenv() нового сеанса R.

  3. Я не совсем уверен, что делает RStudio для опции repos. Вероятно, он автоматически устанавливает эту опцию за кулисы, если она не установлена. Я думаю, что это относительно незначительная проблема. Вы можете установить его в своем .Rprofile, и я думаю, что RStudio должен уважать настройку вашего зеркала CRAN.

Пользователи всегда спрашивали, почему документ Rnw (или документы R Markdown) не скомпилированы в текущем сеансе R. Для нас это в основном сводится к тому, какое из следующих последствий является более удивительным или нежелательным:

  1. Если мы свяжем документ в текущем сеансе R, нет гарантии, что ваши результаты могут быть воспроизведены в другом сеансе R (например, в следующий раз, когда вы откроете RStudio, или ваши соавторы откроют RStudio на своих компьютерах).
  2. Если мы свяжем документ в новом сеансе R, пользователи могут быть удивлены тем, что объекты не найдены (и когда они вводят имена объектов в консоли R, они могут их видеть). Это может быть удивительно, но это также хорошее и раннее напоминание о том, что ваш документ, вероятно, не будет работать в следующий раз.

Подводя итог, я думаю:

  • Вязание в новом сеансе R лучше для воспроизводства;

  • Вязание в текущем сеансе R иногда более удобно (например, вы пытаетесь связать с различными временными объектами R в текущем сеансе). Иногда вам также нужно вязать в текущем сеансе R, особенно когда вы генерируете отчеты в формате PDF программно, например, вы используете цикл (for) для генерации серии отчетов. Невозможно добиться этого только с помощью кнопки "Скомпилировать PDF" (кнопка в основном предназначена только для одного документа Rnw).

Кстати, я думаю, что то, что я сказал выше, может также применяться к кнопкам Knit или Knit HTML, но основной функцией является rmarkdown::render() вместо knitr::knit().