20

我在 Rstudio 中使用 Rmarkdown 键入报告。用knitr转换进去的时候html,还有一个markdown由knitr生成的文件。我将此文件转换pandoc如下:

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

output.docx文件很好,除了一个问题:图形的大小发生了变化,我需要在 Word 中手动调整图形的大小。有什么事情要做,也许是一个选项pandoc,以获得正确的数字大小?

4

4 回答 4

8

k一种简单的方法是在各个块选项中包含比例因子:

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

dpi和全局块选项中的一个变量:

opts_chunk$set(dpi = dpi)

然后您可以在全局环境中设置编织文件之前dpi和之前的值:kRmd

dpi <<- 96    
k <<- 1

或者您可以将它们设置在Rmd文件中的一个块中(例如设置k在第一个块中)。

于 2014-04-13T22:19:14.220 回答
3

这是使用R 脚本中的ImageMagick调整图形大小的解决方案。70%的比例似乎是个不错的选择。

# 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")

resize有关ImageMagick 功能的更多信息: www.perturb.org

于 2013-05-10T19:26:06.903 回答
3

我还想将 R markdown 转换为 html 和 .docx/.odt ,其中的数字具有良好的尺寸和分辨率。到目前为止,我发现最好的方法是在 .md 文档中明确定义图形的分辨率和大小(dpi、fig.width 和 fig.height 选项)。如果你这样做,你就有很好的可用于发布的图表,并且 odt/docx 是可以的。如果您使用远高于默认 72 dpi 的 dpi,问题是图形在 html 文件中看起来太大。以下是我用来处理此问题的 3 种方法(注意,我使用带有 spin() 语法的 R 脚本):

1) 在 knitr 选项中使用 out.extra ='WIDTH="75%"'。这将强制 html 的所有图形占据窗口宽度的 75%。这是一个快速的解决方案,但如果您的地块大小非常不同,则不是最佳解决方案。(注意,我更喜欢使用厘米而不是英寸,因此 /2.54 无处不在)

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) 使用 out.width 和 out.height 指定图形在 html 文件中的大小(以像素为单位)。我使用常量“sc”将绘图的大小缩小为 html 输出。这是更精确的方法,但问题是对于每个图形,您必须同时定义 fig.witdth/height 和 out.width/height ,这真的很无聊!理想情况下,您应该能够在全局选项中指定例如 out.width = 150*fig.width (其中 fig.width 从一个块更改为另一个块)。也许这样的事情是可能的,但我不知道如何。

#+ 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])

请注意,对于这两种解决方案,我认为您无法使用 pandoc 将您的 md 文件直接转换为 odt (不包括数字)。我将 md 转换为 html,然后将 html 转换为 odt(没有尝试过 docx)。类似的东西(如果以前的 R 脚本名称为“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) 只需编译您的文档两次,一次使用低 dpi 值 (~96) 用于 html 输出,一次使用高分辨率 (~300) 用于 odt/docx 输出。这是我现在首选的方式。主要缺点是您必须编译两次,但这对我来说并不是问题,因为我通常只在工作结束时才需要 odt 文件来提供给最终用户。我在工作期间使用 Rstudio 中的 html 笔记本按钮定期编译 html。

#+ 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])

然后使用以下脚本编译 2 个输出(注意这里您可以直接将 md 文件转换为 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")
于 2013-05-27T22:44:31.750 回答
2

这是我的解决方案:破解由 Pandoc 转换的 docx,因为 docx 只是一组 xml 文件,调整图形大小非常简单。

word/document.xml以下是从转换后的 docx 中提取的图形的样子:

<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>

因此,用所需值替换节点&的cx&属性将完成调整大小的工作。以下 R 代码适用于我。最宽的图形将占据变量指定的整行宽度,其余的则按比例调整大小。cywp:extenta:extout.width

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")
于 2013-07-20T01:48:59.943 回答