En `knitr` ¿cómo puedo probar si el resultado será PDF o Word?

Me gustaría incluir contenido específico según el formato que se está creando. En este ejemplo específico, mis tablas se ven terribles en la salida de MS word , pero son geniales en HTML . Me gustaría agregar algunas pruebas para dejar fuera de la tabla dependiendo de la salida.

Aquí hay un pseudocódigo:

 output.format <- opts_chunk$get("output") if(output.format != "MS word"){ print(table1) } 

Estoy seguro de que esta no es la forma correcta de usar opts_chunk , pero este es el límite de mi comprensión de cómo knitr funciona bajo el capó. ¿Cuál sería la forma correcta de probar esto?

Respuesta corta

En la mayoría de los casos, opts_knit$get("rmarkdown.pandoc.to") entrega la información requerida.

De lo contrario, consulte rmarkdown::all_output_formats(knitr::current_input()) y verifique si el valor word_document contiene word_document :

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

Respuesta larga

Supongo que el documento fuente es RMD porque este es el formato de entrada habitual / más común para tejer en diferentes formatos de salida como MS Word, PDF y HTML.

En este caso, knitr opciones knitr no se pueden usar para determinar el formato final de salida porque no importa desde la perspectiva de knitr : para todos los formatos de salida, el trabajo de knitr es tejer el archivo RMD de entrada en un archivo MD. La conversión del archivo MD al formato de salida especificado en el encabezado YAML se realiza en la etapa siguiente, mediante pandoc .

Por lo tanto, no podemos utilizar la opción del paquete knitr::opts_knit$get("out.format") para conocer el formato de salida final, pero en su lugar debemos analizar el encabezado YAML.

Hasta ahora, en teoría. La realidad es un poco diferente. El botón “Knit PDF” / “Knit HTML” de rmarkdown::render llama a rmarkdown::render que a su vez llama a knit . Antes de que esto suceda, render establece una opción de paquete (indocumentado?) rmarkdown.pandoc.to en el formato de salida real. El valor será html , latex o docx , respectivamente, según el formato de salida.

Por lo tanto, si (y solo si) se usa el botón “Knit PDF” / “Knit HTML” de knitr::opts_knit$get("rmarkdown.pandoc.to") , knitr::opts_knit$get("rmarkdown.pandoc.to") se puede usar para determinar el formato de salida. Esto también se describe en esta respuesta y esa publicación de blog .

El problema sigue sin resolverse para el caso de llamar a knit directamente porque entonces rmarkdown.pandoc.to no está configurado. En este caso, podemos explotar la función (no parse_yaml_front_matter ) parse_yaml_front_matter del paquete rmarkdown para analizar el encabezado YAML.

[ Actualización : A partir de rmarkdown 0.9.6, se ha agregado la función all_output_formats (gracias a Bill Denney por señalar esto). Hace que la función personalizada desarrollada a continuación sea obsoleta. Para la producción, use rmarkdown::all_output_formats ! Dejo el rest de esta respuesta como originalmente escrita con fines educativos.]

 --- 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(), ie when using the button in RStudio. rmarkdown:::parse_yaml_front_matter( readLines(knitr::current_input()) )$output ``` 

El ejemplo anterior demuestra el uso (lesness) de opts_knit$get("rmarkdown.pandoc.to") ( opts_knit$get("out.format") ), mientras que la línea que emplea parse_yaml_front_matter devuelve el formato especificado en el campo “output” del encabezado YAML.

La entrada de parse_yaml_front_matter es el archivo de origen como vector de caracteres, tal como lo devuelven readLines . Para determinar el nombre del archivo que se está tejiendo, se usa current_input() como se sugiere en esta respuesta .

Antes de que se pueda usar parse_yaml_front_matter en una instrucción if simple para implementar un comportamiento que es condicional en el formato de salida, se requiere un pequeño refinamiento: La instrucción mostrada arriba puede devolver una lista si hay parámetros YAML adicionales para la salida como en este ejemplo:

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

La siguiente función auxiliar debe resolver este problema:

 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]) } } 

Se puede usar en construcciones tales como

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

Tenga en cuenta que getOutputFormat usa solo el primer formato de salida especificado, por lo que con el siguiente encabezado solo se devuelve html_document :

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

Sin embargo, esto no es muy restrictivo. Cuando se utiliza el botón "Knit HTML" / "Knit PDF" de RStudio (junto con el menú desplegable junto a él para seleccionar el tipo de salida), RStudio reorganiza el encabezado YAML de modo que el formato de salida seleccionado sea el primero en la lista. Los múltiples formatos de salida son (AFAIK) solo relevantes cuando se usa rmarkdown::render con output_format = "all" . Y: en ambos casos, se puede usar rmarkdown.pandoc.to , que de todos modos es más fácil.

Desde knitr 1.18, puede usar las dos funciones

 knitr::is_html_output() 

y

 knitr::is_latex_output() 

Un punto adicional: las respuestas anteriores no funcionan para un html_notebook , ya que el código se está ejecutando directamente allí y knitr::current_input() no responde. Si conoce el nombre del documento, puede llamar a all_output_formats como se all_output_formats anteriormente, especificando el nombre explícitamente. No sé si hay otra forma de hacer esto.

Solo quiero añadir un poco de aclaración aquí, ya que a menudo renderizo el mismo archivo Rmarkdown (* .Rmd) en múltiples formatos (* .html, * .pdf, * .docx), así que en lugar de querer saber si el formato de el interés se enumera entre los especificados en la materia principal yaml (es decir, "word_document" %in% rmarkdown::all_output_formats(knitr::current_input() ), quiero saber qué formato se está procesando actualmente. Para hacerlo, puede:

  1. Obtenga el primer elemento de formatos enumerados en la parte frontal: rmarkdown::all_output_formats(knitr::current_input()[1] ; o

  2. Obtenga el nombre de formato de salida predeterminado: rmarkdown::default_output_format(knitr::current_input())$name

Por ejemplo…

 --- 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"){ #... } ```