add vertical space above and below figures/code ch

2019-06-05 17:33发布

问题:

I am knitting from Rmd to PDF. I'd like to add vertical space above and below figures/code chunks to separate this content from body text. I've done this successfully for Rnw files by adding the following to my preamble see this answer:

\renewenvironment{knitrout}{\vspace{1em}}{\vspace{1em}}

I tried adding this line to header-includes in the yaml section of my Rmd file, but it did not work. I turned on the option to keep the interim tex file, and I see there is no knitrout environment in the tex.

Instead, (i) code chunks are wrapped in \begin{Shaded}, (ii) figures in \begin{figure}, and (iii) tables in \begin{longtable}.

I tried solving the problem for code chunks (i) by adding the following to header-includes:

\renewenvironment{Shaded}{\vspace{1em}}{\vspace{1em}}

This added space, but dropped the shaded background. I'm not sure how to fix this or address the figures (ii) and tables (iii).

R version 3.3.2 (2016-10-31)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS Sierra 10.12.4

回答1:

I think you need to modify hooks: https://yihui.name/knitr/hooks/
I give you some examples. Once you understand how it works, you can add your own modifications.

Add vspace before source code

The hook to be modified:

```{r setup_source, include=FALSE}
hook_source_def = knitr::knit_hooks$get('source')
knitr::knit_hooks$set(source = function(x, options) {
  if (!is.null(options$vspaceecho)) {
    begin <- paste0("\\vspace{", options$vspaceecho, "}")
    stringr::str_c(begin, hook_source_def(x, options))
  } else {
    hook_source_def(x, options)
  }
})
```

How to call this modification:

```{r vspace, vspaceecho='2cm', echo=TRUE}
summary(cars)
```

Add vspace after R output

The hook to be modified

```{r setup_output, include=FALSE}
hook_output_def = knitr::knit_hooks$get('output')
knitr::knit_hooks$set(output = function(x, options) {
  if (!is.null(options$vspaceout)) {
    end <- paste0("\\vspace{", options$vspaceout, "}")
    stringr::str_c(hook_output_def(x, options), end)
  } else {
    hook_output_def(x, options)
  }
})
```

How to call this modification:

```{r vspaceafter, vspaceout='1cm'}
summary(cars)
```

Add vspace before and after a figure

You can create a new environment to embed a figure. This requires to add a trick to make pandoc ignore \begin and \end, otherwise pandoc do not consider code inside environment as markdown syntax.

Create an external tex file to be called in YAML

This text inside

\newenvironment{plotspace}[1]{#1}
% -- command for pandoc trick with \begin and \end -- %
\newcommand{\nopandoc}[1]{#1} 

Call tex file in YAML

output: 
  pdf_document:
    keep_tex: yes
    include:
      in_header: header.tex

The hook function to include in your code

hook_plot_def = knitr::knit_hooks$get('plot')
knitr::knit_hooks$set(plot = function(x, options) {
  if (!is.null(options$vspaceplot)) {
    begin <- paste0("\\nopandoc{\\begin{plotspace}}\n\\vspace{", options$vspaceplot, "}\n")
    end <- paste0("\n\\vspace{", options$vspaceplot, "}\n\\nopandoc{\\end{plotspace}}")
    stringr::str_c(begin, hook_plot_def(x, options), end)
  } else {
    hook_plot_def(x, options)
  }
})

How to call it

```{r plotvspace, vspaceplot='2em', fig.cap='Figure with vspace'}
plot(cars)
```

Retrieve Shaded in a renew environment

As you tried to renew Shaded environment, you can do it as follows in your additional header.tex file.

\renewenvironment{Shaded}
{
  \vspace{2cm}%
  \begin{snugshade}%
}{%
  \end{snugshade}%
  \vspace{5cm}%
}