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

В `knitr`, как я могу проверить, будет ли выход PDF или word?

Я хотел бы включить конкретный контент на основе того, какой формат создается. В этом конкретном примере мои таблицы выглядят ужасно в выводе MS word, но отлично в HTML. Я хотел бы добавить в некоторый тест, чтобы оставить таблицу в зависимости от результата.

Здесь некоторый псевдокод:

output.format <- opts_chunk$get("output")

if(output.format != "MS word"){
print(table1)
}

Я уверен, что это не правильный способ использования opts_chunk, но это предел моего понимания того, как knitr работает под капотом. Каким будет правильный способ проверить это?

4b9b3361

Ответ 1

Краткий ответ

В большинстве случаев opts_knit$get("rmarkdown.pandoc.to") предоставляет требуемую информацию.

В противном случае запросите rmarkdown::all_output_formats(knitr::current_input()) и проверьте, содержит ли возвращаемое значение word_document:

if ("word_document" %in% rmarkdown::all_output_formats(knitr::current_input()) {
  # Word output
}

Длинный ответ

Я предполагаю, что исходный документ RMD, потому что это обычный/наиболее распространенный формат ввода для вязания в разные выходные форматы, такие как MS Word, PDF и HTML.

В этом случае параметры knitr не могут использоваться для определения окончательного формата вывода, поскольку это не имеет значения с точки зрения knitr: для всех выходных форматов knitr задание заключается в вязании входного файла RMD в файл MD. Преобразование файла MD в выходной формат, указанный в заголовке YAML, выполняется на следующем этапе, pandoc.

Поэтому мы не можем использовать параметр knitr::opts_knit$get("out.format"), чтобы узнать окончательный формат вывода, но нам нужно проанализировать заголовок YAML.

До сих пор в теории. Реальность немного отличается. Кнопка RStudio "Вязать PDF" / "Вязать HTML" вызывает rmarkdown::render, которая в свою очередь вызывает knit. Прежде чем это произойдет, render устанавливает (недокументированный?) Вариант пакета rmarkdown.pandoc.to в фактический формат вывода. Значение будет html, latex или docx соответственно, в зависимости от формата вывода.

Следовательно, если (и только если) используется кнопка RStudio "Вязать PDF" / "Вязать HTML" , knitr::opts_knit$get("rmarkdown.pandoc.to") может использоваться для определения формата вывода. Это также описано в этом ответе и в этом сообщении в блоге.

Проблема остается нерешенной для случая прямого вызова knit, потому что тогда rmarkdown.pandoc.to не задан. В этом случае мы можем использовать (непортированную) функцию parse_yaml_front_matter из пакета rmarkdown для анализа заголовка YAML.

[ Обновление: с rmarkdown 0.9.6 добавлена ​​функция all_output_formats (спасибо Bill Denney за указывая на это). Это делает пользовательскую функцию, разработанную ниже устаревшей - для производства, используйте rmarkdown::all_output_formats! Я оставляю оставшуюся часть этого ответа как первоначально написанную для образовательных целей.]

---
output: html_document
---
```{r}
knitr::opts_knit$get("out.format") # Not informative.

knitr::opts_knit$get("rmarkdown.pandoc.to") # Works only if knit() is called via render(), i.e. when using the button in RStudio.

rmarkdown:::parse_yaml_front_matter(
    readLines(knitr::current_input())
    )$output
```

В приведенном выше примере показано использование (lesness) для opts_knit$get("rmarkdown.pandoc.to") (opts_knit$get("out.format")), а строка, использующая parse_yaml_front_matter, возвращает формат, указанный в поле "output" заголовка YAML.

Ввод parse_yaml_front_matter является исходным файлом как символьный вектор, возвращаемый readLines. Чтобы определить имя вложенного файла, current_input(), как предложено в этом ответе, используется.

Прежде чем parse_yaml_front_matter может использоваться в простом выражении if для реализации поведения, которое является условным для выходного формата, требуется небольшое уточнение: приведенный выше оператор может возвращать список, если есть дополнительные параметры YAML для вывода, как в этом примере:

---
output: 
  html_document: 
    keep_md: yes
---

Следующая вспомогательная функция должна решить эту проблему:

getOutputFormat <- function() {
  output <- rmarkdown:::parse_yaml_front_matter(
    readLines(knitr::current_input())
    )$output
  if (is.list(output)){
    return(names(output)[1])
  } else {
    return(output[1])
  }
}

Его можно использовать в конструкциях, таких как

if(getOutputFormat() == 'html_document') {
   # do something
}

Обратите внимание, что getOutputFormat используется только указанный первый формат вывода, поэтому при следующем заголовке возвращается только html_document:

---
output:
  html_document: default
  pdf_document:
    keep_tex: yes
---

Однако это не очень ограничительно. Когда используется кнопка RStudio "Вязать HTML" / "Вязать PDF" (вместе с выпадающим меню рядом с ней для выбора типа вывода), RStudio перестраивает заголовок YAML таким образом, чтобы выбранный формат вывода был первым форматом в списке. Несколько форматов вывода (AFAIK) применимы только при использовании rmarkdown::render с output_format = "all". И: В обоих случаях можно использовать rmarkdown.pandoc.to, что проще в любом случае.

Ответ 2

Еще одна точка: приведенные выше ответы не работают для html_notebook, так как код выполняется непосредственно там, а knitr::current_input() не отвечает. Если вы знаете имя документа, вы можете вызвать all_output_formats, как указано выше, указав имя явно. Я не знаю, есть ли другой способ сделать это.

Ответ 3

Просто хочу добавить немного разъяснений здесь, так как я часто представляю один и тот же файл Rmarkdown (*.Rmd) в несколько форматов (*.html, *.pdf, *.docx), поэтому вместо того, чтобы знать, формат интереса указан среди тех, которые указаны в yaml переднего массива (т.е. "word_document" %in% rmarkdown::all_output_formats(knitr::current_input()), я хочу знать, какой формат в настоящее время отображается. Для этого вы можете:

  • Получить первый элемент форматов, перечисленных в разделе: rmarkdown::all_output_formats(knitr::current_input()[1]; или

  • Получить имя выходного формата по умолчанию: rmarkdown::default_output_format(knitr::current_input())$name

Например...

---
title: "check format"
output:
  html_document: default
  pdf_document: default
  word_document: default
---

```{r}
rmarkdown::all_output_formats(knitr::current_input())[1]
```

```{r}
rmarkdown::default_output_format(knitr::current_input())$name
```

```{r}
fmt <- rmarkdown::default_output_format(knitr::current_input())$name

if (fmt == "pdf_document"){
  #...
}

if (fmt == "word_document"){
  #...
}
```

Ответ 4

Так как knitr 1,18, вы можете использовать две функции

knitr::is_html_output()

и

knitr::is_latex_output()