online engine image markdown docx knitr pandoc

image - engine - Tamaños de figuras con conversión de pandoc de markdown a docx



pandoc pdf-engine (4)

Aquí hay una solución para cambiar el tamaño de las figuras usando ImageMagick desde una secuencia de comandos R. La relación del 70% parece ser una buena opción.

# the path containing the Rmd file : wd <- "..." setwd(wd) # the folder containing the figures : fig.path <- paste0(wd, "/figure") # all png figures : figures <- list.files(fig.path, pattern=".png", all.files=TRUE) # (safety) create copies of the original files dir.create(paste0(fig.path,"_copy")) for(i in 1:length(figures)){ fig <- paste0(fig.path, "/", figures[i]) file.copy(fig,"figure_copy") } # resize all figures for(i in 1:length(figures)){ fig <- paste0(fig.path, "/", figures[i]) comm <- paste("convert -resize 70%", fig, fig) shell(comm) } # then run pandoc from a command line # or from the pandoc() function : library(knitr) pandoc("MyReport.md", "docx")

Más información sobre la función de cambio de resize de ImageMagick: www.perturb.org

Escribo un informe con Rmarkdown en Rstudio. Al convertirlo en html con knitr, también hay un archivo de reducción producido por knitr. Convierto este archivo con pandoc siguiente manera:

pandoc -f markdown -t docx input.md -o output.docx

El archivo output.docx está bien, excepto por un problema: los tamaños de las figuras están alterados, necesito cambiar manualmente el tamaño de las figuras en Word. ¿Hay algo que hacer, tal vez una opción con pandoc , para obtener los tamaños de figuras correctos?


También quiero transformar una rebaja R en un html y un .docx / .odt con cifras de buen tamaño y resolución. Hasta ahora, descubrí que la mejor manera de hacerlo es definir explícitamente la resolución y el tamaño de los gráficos en el documento .md (dpi, fig.width y fig.height options). Si haces esto, tienes buenos gráficos utilizables para publicación y el odt / docx está bien. El problema si usa ppp mucho más alto que el valor predeterminado de 72 ppp es que los gráficos se verán demasiado grandes en el archivo html. Aquí hay 3 enfoques que he usado para manejar esto (Nota: yo uso scripts R con la sintaxis spin ()):

1) use out.extra = ''WIDTH = "75%"'' en las opciones knitr. Esto obligará a todos los gráficos del html a ocupar el 75% del ancho de la ventana. Esta es una solución rápida, pero no óptima si tiene parcelas con tamaños muy diferentes. (NB Prefiero trabajar con centímetros en lugar de pulgadas, de ahí el /2.54 en todas partes)

library(knitr) opts_chunk$set(echo = FALSE, dev = c("png", "pdf"), dpi = 400, fig.width = 8/2.54, fig.height = 8/2.54, out.extra =''WIDTH="75%"'' ) data(iris) #'' # Iris datatset summary(iris) boxplot(iris[,1:4]) #+ fig.width=14/2.54, fig.height=10/2.54 par(mar = c(2,2,2,2)) pairs(iris[,-5])

2) use out.width y out.height para especificar el tamaño de los gráficos en píxeles en el archivo html. Uso una "sc" constante para reducir el tamaño de la gráfica en la salida html. Este es el enfoque más preciso, pero el problema es que para cada gráfico tiene que definir tanto fig.witdth / height como out.width / height ¡y esto es realmente aburrido! Idealmente, debería ser capaz de especificar en las opciones globales que, por ejemplo, out.width = 150 * fig.width (donde fig.width cambia de chunk a chunk). Tal vez algo así es posible, pero no sé cómo.

#+ echo = FALSE library(knitr) sc <- 150 opts_chunk$set(echo = FALSE, dev = c("png", "pdf"), dpi = 400, fig.width = 8/2.54, fig.height = 8/2.54, out.width = sc*8/2.54, out.height = sc*8/2.54 ) data(iris) #'' # Iris datatset summary(iris) boxplot(iris[,1:4]) #+ fig.width=14/2.54, fig.height=10/2.54, out.width= sc * 14/2.54, out.height= sc * 10/2.54 par(mar = c(2,2,2,2)) pairs(iris[,-5])

Tenga en cuenta que para estas dos soluciones, creo que no puede transformar directamente su archivo md en odt con pandoc (las cifras no están incluidas). Transformé el md en html y luego el html en odt (no intenté para docx). Algo así (si los scripts R anteriores son nombres "figsize1.R"):

library(knitr) setwd("/home/gilles/") spin("figsize1.R") system("pandoc figsize1.md -o figsize1.html") system("pandoc figsize1.html -o figsize1.odt")

3) Simplemente compile su documento dos veces, una vez con un valor bajo de ppp (~ 96) para la salida html y una vez con alta resolución (~ 300) para la salida odt / docx. Esta es mi forma preferida ahora. La principal desventaja es que debe compilar dos veces, pero esto no es realmente un problema para mí, ya que generalmente necesito el archivo odt solo al final del trabajo para proporcionarlo a los usuarios finales. Recopilo regularmente el html durante el trabajo con el botón del cuaderno html en Rstudio.

#+ echo = FALSE library(knitr) opts_chunk$set(echo = FALSE, dev = c("png", "pdf"), fig.width = 8/2.54, fig.height = 8/2.54 ) data(iris) #'' # Iris datatset summary(iris) boxplot(iris[,1:4]) #+ fig.width=14/2.54, fig.height=10/2.54 par(mar = c(2,2,2,2)) pairs(iris[,-5])

Luego compila las 2 salidas con la siguiente secuencia de comandos (NB aquí puedes transformar directamente el archivo md en html):

library(knitr) setwd("/home/gilles") opts_chunk$set(dpi=96) spin("figsize3.R", knit=FALSE) knit2html("figsize3.Rmd") opts_chunk$set(dpi=400) spin("figsize3.R") system("pandoc figsize3.md -o figsize3.odt")


Una manera fácil consiste en incluir un factor de escala k en las opciones de fragmentos individuales:

{r, fig.width=8*k, fig.height=6*k}

y una dpi variable en las opciones globales de fragmentos:

opts_chunk$set(dpi = dpi)

Luego puede establecer los valores de dpi k antes de tejer el archivo Rmd en el entorno global:

dpi <<- 96 k <<- 1

o puede configurarlos en un fragmento en el archivo Rmd (por ejemplo, establecer k en el primer fragmento).


Aquí está mi solución: hackear el docx convertido por Pandoc, ya que docx es simplemente un paquete de archivos xml y ajustar los tamaños de las figuras es bastante sencillo.

A continuación, se muestra el aspecto de una figura en la word/document.xml extraída de un docx convertido:

<w:p> <w:r> <w:drawing> <wp:inline> <wp:extent cx="1524000" cy="1524000" /> ... <a:graphic> <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"> <pic:pic> ... <pic:blipFill> <a:blip r:embed="rId23" /> ... </pic:blipFill> <pic:spPr bwMode="auto"> <a:xfrm> <a:off x="0" y="0" /> <a:ext cx="1524000" cy="1524000" /> </a:xfrm> ... </pic:spPr> </pic:pic> </a:graphicData> </a:graphic> </wp:inline> </w:drawing> </w:r> </w:p>

Por lo tanto, sustituir los atributos cx y cy de los nodos wp:extent & a:ext con el valor deseado haría el trabajo de cambio de tamaño. El siguiente código R funciona para mí. La figura más ancha tomaría el ancho de una línea completa especificada por la variable out.width , y el resto se redimensionaría proporcionalmente.

require(XML) ## default linewidth (inch) for Word 2003 out.width <- 5.77 docx.file <- "report.docx" ## unzip the docx converted by Pandoc system(paste("unzip", docx.file, "-d temp_dir")) document.xml <- "temp_dir/word/document.xml" doc <- xmlParse(document.xml) wp.extent <- getNodeSet(xmlRoot(doc), "//wp:extent") a.blip <- getNodeSet(xmlRoot(doc), "//a:blip") a.ext <- getNodeSet(xmlRoot(doc), "//a:ext") figid <- sapply(a.blip, xmlGetAttr, "r:embed") figname <- dir("temp_dir/word/media/") stopifnot(length(figid) == length(figname)) pdffig <- paste("temp_dir/word/media/", ## in case figure ids in docx are not in dir''ed order sort(figname)[match(figid, substr(figname, 1, nchar(figname) - 4))], sep="") ## get dimension info of included pdf figures pdfsize <- do.call(rbind, lapply(pdffig, function (x) { fig.ext <- substr(x, nchar(x) - 2, nchar(x)) pp <- pipe(paste(ifelse(fig.ext == ''pdf'', "pdfinfo", "file"), x, sep=" ")) pdfinfo <- readLines(pp); close(pp) sizestr <- unlist(regmatches(pdfinfo, gregexpr("[[:digit:].]+ X [[:digit:].]+", pdfinfo, ignore.case=T))) as.numeric(strsplit(sizestr, split=" x ")[[1]]) })) ## resizing pdf figures in xml DOM, with the widest figure taking up a line''s width wp.cx <- round(out.width*914400*pdfsize[,1]/max(pdfsize[,1])) wp.cy <- round(wp.cx*pdfsize[, 2]/pdfsize[, 1]) wp.cx <- as.character(wp.cx) wp.cy <- as.character(wp.cy) sapply(1:length(wp.extent), function (i) xmlAttrs(wp.extent[[i]]) <- c(cx = wp.cx[i], cy = wp.cy[i])); sapply(1:length(a.ext), function (i) xmlAttrs(a.ext[[i]]) <- c(cx = wp.cx[i], cy = wp.cy[i])); ## save hacked xml back to docx saveXML(doc, document.xml, indent = F) setwd("temp_dir") system(paste("zip -r ../", docx.file, " *", sep="")) setwd("..") system("rm -fr temp_dir")