【问题标题】:knitr - How to align code and plot side by sideknitr - 如何对齐代码并并排绘制
【发布时间】:2012-06-14 10:08:35
【问题描述】:

是否有一种简单的方法(例如,通过块选项)来获取块的源代码及其并排生成的图,如this document 的第 8 页(以及其他)?

我尝试使用out.width="0.5\\textwidth", fig.align='right',这使得绘图正确地仅占据页面的一半并向右对齐,但源代码显示在其顶部,这是正常行为。 我想把它放在情节的左边。

谢谢

示例代码:

<<someplot, out.width="0.5\\textwidth", fig.align='right'>>=
plot(1:10)
@

【问题讨论】:

  • 该演示文稿很可能是使用 \columns{} 环境与 beamer 放在一起的。您是在 LaTeX 中使用投影仪尝试同样的事情,还是通过其他引擎(普通 LaTeX 等)进行渲染?
  • @GavinSimpson 正确,I used \columns
  • 在标准的乳胶文档中,我会改用minipage
  • @baptiste 我认为您可以使用上面的链接作为这个问题的答案。
  • 我现在才看到这些回复...谢谢!亿辉有机会内置这个功能吗?我可以用钩子实现这个吗?我之所以如此,是因为据我了解,所有内容都是作为 knitr 中的钩子实现的,甚至是内置功能:)

标签: r knitr


【解决方案1】:

嗯,这最终比我预期的要棘手。

在 LaTeX 方面,adjustbox package 让您可以很好地控制并排框的对齐方式,正如 tex.stackexchange.com 上的 in this excellent answer 所展示的那样。所以我的一般策略是用 LaTeX 代码包装指定 R 块的格式化、整理、彩色输出:(1)将它放在一个调整框环境中; (2) 在右侧的另一个调整框环境中包含块的图形输出。为此,我需要将 knitr 的默认块输出挂钩替换为自定义的,在文档的 &lt;&lt;setup&gt;&gt;= 块的 (2) 部分中定义。

&lt;&lt;setup&gt;&gt;=(1) 部分定义了一个块钩子,可用于在每个块的基础上临时设置 R 的任何全局选项(特别是这里,options("width"))。 See here 的问题和答案只处理此设置的一部分。

最后,(3) 节定义了一个 knitr “模板”,这是一组需要在每次生成并排的代码块和图形时设置的选项。定义后,它允许用户通过在块的标题中输入opts.label="codefig" 来触发所有必需的操作。

\documentclass{article}

\usepackage{adjustbox}            %% to align tops of minipages
\usepackage[margin=1in]{geometry} %% a bit more text per line

\begin{document}

<<setup, include=FALSE, cache=FALSE>>=
## These two settings control text width in codefig vs. usual code blocks
partWidth <- 45
fullWidth <- 80
options(width = fullWidth)

##  (1) CHUNK HOOK FUNCTION
##   First, to set R's textual output width on a per-chunk basis, we
## need to define a hook function which temporarily resets global R's
## option() settings, just for the current chunk
knit_hooks$set(r.opts=local({
    ropts <- NA
    function(before, options, envir) {
        if (before) {
            ropts <<- options(options$r.opts)
        } else {
            options(ropts)
        }
    }
}))

## (2) OUTPUT HOOK FUNCTION

##   Define a custom output hook function. This function processes _all_
## evaluated chunks, but will return the same output as the usual one,
## UNLESS a 'codefig' argument appeared in the chunk's header.  In that
## case, wrap the usual textual output in LaTeX code placing it in a
## narrower adjustbox environment and setting the graphics that it
## produced in another box beside it.

defaultChunkHook <- environment(knit_hooks[["get"]])$defaults$chunk

codefigChunkHook <- function (x, options) {
        main <- defaultChunkHook(x, options)
        before <-
            "\\vspace{1em}\n
             \\adjustbox{valign=t}{\n
             \\begin{minipage}{.59\\linewidth}\n"
        after <-
            paste("\\end{minipage}}
                   \\hfill
                   \\adjustbox{valign=t}{",
                   paste0("\\includegraphics[width=.4\\linewidth]{figure/",
                           options[["label"]], "-1.pdf}}"), sep="\n")
    ## Was a codefig option supplied in chunk header?
    ## If so, wrap code block and graphical output with needed LaTeX code.
    if (!is.null(options$codefig)) {
      return(sprintf("%s %s %s", before, main, after))
    } else {
      return(main)
    }
}

knit_hooks[["set"]](chunk = codefigChunkHook)


## (3) TEMPLATE
##   codefig=TRUE is just one of several options needed for the
## side-by-side code block and a figure to come out right. Rather
## than typing out each of them in every single chunk header, we
## define a _template_ which bundles them all together. Then we can
## set all of those options simply by typing opts.label="codefig".

opts_template[["set"]](
codefig = list(codefig=TRUE, fig.show = "hide",
               r.opts = list(width=partWidth),
               tidy = TRUE,
               tidy.opts = list(width.cutoff = partWidth)))
@

A chunk without \texttt{opts.label="codefig"} set...
<<A>>=
1:60
@

\texttt{opts.label="codefig"} \emph{is} set for this one

<<B, opts.label="codefig", fig.width=8, cache=FALSE>>=
library(raster)
library(RColorBrewer)

## Create a factor raster with a nice RAT (Rast. Attr. Table)
r <- raster(matrix(sample(1:10, 100, replace=TRUE), ncol=10, nrow=10))
r <- as.factor(r)
rat <- levels(r)[[1]]
rat[["landcover"]] <- as.character(1:10)
levels(r) <- rat

## To get a nice grid...
p <- as(r, "SpatialPolygonsDataFrame")

## Plot it
plot(r, col = brewer.pal("Set3", n=10),
     legend = FALSE, axes = FALSE, box = FALSE)
plot(p, add = TRUE)
text(p, label =  getValues(r))
@

\texttt{opts.label="codefig"} not set, and all settings back to ``normal''.
<<C>>=
lm(mpg ~ cyl + disp + hp + wt + gear, data=mtcars)
@


\end{document}

【讨论】:

  • 老实说,花了你足够长的时间:-) +1
【解决方案2】:

我看到了 3 种可能性

  • 对于beamer 演示文稿,我也会选择\begin{columns} ... \end{columns}
  • 如果只有这样一个情节:Minipages
  • Here我使用了一个表格(列代码和列结果)。 (这个例子是“正常的”Sweave)

对于所有这三个,块选项将具有include = FALSE,并且情节将由\includegraphics[]{}“手动”放置到正确的位置。

【讨论】:

  • 我支持这种方法。
【解决方案3】:

您可以在 PerformanceAnalytics 或 gplots 包中的“textplot”中显示文本。

(小)缺点:据我所知,无法突出显示语法。

示例代码:

```{r fig.width=8, fig.height=5, fig.keep = 'last', echo=FALSE}
suppressMessages(library(PerformanceAnalytics))
layout(t(1:2))
textplot('plot(1:10)')
plot(1:10)
```

【讨论】:

    猜你喜欢
    • 2016-09-04
    • 2018-05-31
    • 2020-12-21
    • 2019-06-21
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    相关资源
    最近更新 更多