В `knitr` как я могу проверить, будет ли вывод PDF или word?
Я хотел бы включить конкретный контент в зависимости от того, какой формат создается. В этом конкретном примере мои таблицы выглядят ужасно в MS word
выходной, но отличный в HTML
, Я хотел бы добавить в некоторый тест, чтобы пропустить таблицу в зависимости от вывода.
Вот некоторый псевдокод:
output.format <- opts_chunk$get("output")
if(output.format != "MS word"){
print(table1)
}
Я уверен, что это не правильный способ использования opts_chunk
, но это предел моего понимания того, как knitr
работает под капотом. Какой будет правильный способ проверить это?
5 ответов
Короткий ответ
В большинстве случаев, 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.
Пока в теории. Реальность немного отличается. Кнопки RStdio "Knit PDF"/"Knit HTML" rmarkdown::render
который в свою очередь вызывает knit
, Прежде чем это произойдет, render
устанавливает (недокументированный?) параметр пакета rmarkdown.pandoc.to
к фактическому формату вывода. Значение будет html
, latex
или же docx
соответственно в зависимости от формата вывода.
Поэтому, если (и только если) используется кнопка "Knit PDF"/"Knit HTML" в RStudio, knitr::opts_knit$get("rmarkdown.pandoc.to")
может быть использован для определения выходного формата. Это также описано в этом ответе и в этом блоге.
Проблема остается нерешенной для случая вызова knit
прямо потому что тогда rmarkdown.pandoc.to
не установлен. В этом случае мы можем использовать (неэкспортированную) функцию parse_yaml_front_matter
от rmarkdown
пакет для анализа заголовка YAML.
[ Обновление: по состоянию на rmarkdown
0.9.6, функция all_output_formats
был добавлен (спасибо Биллу Денни за указание на это). Это делает пользовательскую функцию, разработанную ниже, устаревшей - для производства, использования 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
```
Пример выше демонстрирует использование (меньшинство) 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 "Knit HTML"/"Knit PDF" используется (наряду с раскрывающимся меню рядом с ним для выбора типа вывода), RStudio переупорядочивает заголовок YAML таким образом, чтобы выбранный формат вывода был первым форматом в списке. Несколько выходных форматов (AFAIK) актуальны только при использовании rmarkdown::render
с output_format = "all"
, И: в обоих случаях rmarkdown.pandoc.to
можно использовать, что проще в любом случае.
Поскольку knitr
1.18, вы можете использовать две функции
knitr::is_html_output()
а также
knitr::is_latex_output()
Просто хочу добавить немного пояснения, так как я часто визуализирую один и тот же файл 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"){
#...
}
```
Еще один момент: приведенные выше ответы не работают для html_notebook
поскольку код выполняется прямо там и knitr::current_input()
не отвечает. Если вы знаете название документа, вы можете позвонить all_output_formats
как указано выше, указав имя явно. Я не знаю, есть ли другой способ сделать это.
Это то, что я использую
library(stringr)
first_output_format <-
names(rmarkdown::metadata[["output"]])[1]
if (!is.null(first_output_format)) {
my_output <- str_split(first_output_format,"_")[[1]][1]
} else {
my_output = "unknown"
}