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

Как запросить ранний выход при вставке документа Rmd?

Скажем, у вас есть документ с уценкой R, который не будет отображаться чисто.

Я знаю, что вы можете установить опцию knitr chunk error на TRUE, чтобы продолжить эту оценку даже при наличии ошибок. Вы можете сделать это для отдельного фрагмента с помощью error = TRUE или более глобальным способом через knitr::opts_chunk$set(error = TRUE).

Но иногда бывают ошибки, которые по-прежнему являются фатальными для процесса вязания. Два примера, с которыми я недавно столкнулся: попытка unlink() текущего рабочего каталога (oops!) И вызов rstudioapi::getVersion() из встроенного R-кода, когда RStudio недоступен. Существует ли общее описание таких ошибок, т.е. Те, которые недоступны для error = TRUE? Есть ли способ вынести ошибки в встроенном R-коде и в кусках?

Кроме того, существуют ли более официальные способы остановить вязание раньше или автоматизировать отладку в этой ситуации?

4b9b3361

Ответ 1

Чтобы выйти из процесса вязания рано, вы можете использовать функцию knitr::knit_exit() в любом месте исходного документа (в фрагменте кода или встроенном выражении). Когда вызывается knit_exit(), knitr будет игнорировать всю оставшуюся часть документа и выписать результаты, которые он собрал до сих пор.

В настоящий момент нельзя допускать ошибки в встроенном R-коде. Вы должны убедиться, что встроенный R-код всегда работает без ошибок 1. Если ошибки происходят, вы должны увидеть диапазон строк, которые вызвали ошибку из журнала knitr в консоли, формы Quitting from lines x1-x2 (filename.Rmd). Затем вы можете перейти к файлу filename.Rmd и посмотреть, что не так с линиями от x1 до x2. То же самое относится к фрагментам кода с опцией chunk error = FALSE.

Помимо описанных выше типов ошибок, может оказаться сложным найти источник проблемы. Например, когда вы непреднамеренно unlink() текущий каталог, он не должен останавливать процесс вязания, потому что unlink() преуспел в любом случае. Вы можете столкнуться с проблемами после процесса вязания, например, LaTeX/HTML не может найти файлы выходных фигур. В этом случае вы можете попробовать применить knit_exit() ко всем фрагментам кода в документе один за другим. Один из способов добиться этого - настроить кусок для запуска knit_exit() после определенного фрагмента. Ниже приведен пример использования линейного поиска (вы можете улучшить его, используя вместо этого bisection):

#' Render an input document chunk by chunk until an error occurs
#' 
#' @param input the input filename (an Rmd file in this example)
#' @param compile a function to compile the input file, e.g. knitr::knit, or
#'   rmarkdown::render
knit_debug = function(input, compile = knitr::knit) {
  library(knitr)
  lines = readLines(input)
  chunk = grep(all_patterns$md$chunk.begin, lines)  # line number of chunk headers

  knit_hooks$set(debug = function(before) {
    if (!before) {
      chunk_current <<- chunk_current + 1
      if (chunk_current >= chunk_num) knit_exit()
    }
  })

  opts_chunk$set(debug = TRUE)

  # try to exit after the i-th chunk and see which chunk introduced the error
  for (chunk_num in seq_along(chunk)) {
    chunk_current = 0  # a chunk counter, incremented after each chunk
    res = try(compile(input))
    if (inherits(res, 'try-error')) {
      message('The first error came from line ', chunk[chunk_num])
      break
    }
  }
}

  • Это по дизайну. Я думаю, что неплохо иметь error = TRUE для фрагментов кода, поскольку иногда мы хотим показывать ошибки, например, для целей обучения. Однако, если я допускаю ошибки для встроенного кода, авторы могут не распознать фатальные ошибки во встроенном коде. Встроенный код обычно используется для встраивания значений inline, и я не думаю, что это имеет смысл, если встроенное значение является ошибкой. Представьте предложение в отчете, например The P-value of my test is ERROR, и если knitr не сообщит об ошибке, авторы потребуют очень внимательно прочитать отчет, чтобы определить эту проблему. Я думаю, что плохая идея - полагаться на человеческие глаза, чтобы найти такие ошибки.

Ответ 2

IMHO, сложность отладки документа Rmd является предупреждением о том, что что-то не так. У меня есть эмпирическое правило: делайте тяжелую работу за пределами Rmd. Сделайте рендеринг внутри Rmd и только рендеринг. Это упрощает код Rmd.

Мои большие программы R выглядят так.

data <- loadData()
analytics <- doAnalytics(data)
rmarkdown::render("theDoc.Rmd", envir=analytics)

(Здесь doAnalytics возвращает список или среду. Этот список или среда передается в документ Rmd через параметр envir, делая результаты вычислений аналитики доступными внутри документа.)

Функция doAnalytics выполняет сложные вычисления. Я могу отлаживать его с помощью обычных инструментов, и я могу легко проверить его вывод. К тому моменту, когда я вызываю rmarkdown:: render, я знаю, что жесткий материал работает правильно. Код Rmd - это просто "распечатать это" и "формат", который легко отлаживать.

Это разделение ответственности хорошо послужило мне, и я могу порекомендовать его. Особенно по сравнению с задачей сгибания ума отладки сложных вычислений, зарытых внутри динамически оформленного документа.