2

Is there a clean way to "tile" or create some sort of table-like layout in rmarkdown? For example, in RShiny you can setup a grid of sorts and then place elements (e.g., text, tables, plots, etc...) in these slots to really control your look. I am open to the output being in HTML, Word, or PDF if markdown is not the best way. As an example, consider this file:

---
title: "Test File"
output: html_document
---

## R Markdown

How do put these side-by-side?

```{r text, echo=FALSE}
summary(cars)
```

```{r plot, echo=FALSE}
plot(speed ~ dist, cars)
```

Can I place the summary() output next to the plot() output? What if I wanted to go three wide: plot() | summary() | summary?

I'd be open to another format / construct as well. I have tried officer but struggle to get this type of alignment in Word to work.

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
  • 1
    [This post may help which uses CSS](https://stackoverflow.com/questions/31753897/2-column-section-in-r-markdown) – emilliman5 Jan 30 '19 at 13:47
  • I suppose columns may just be the answer. I was hoping for slightly more control, but I am sure I can come up with workarounds –  Jan 30 '19 at 14:10
  • 2
    The type of output is going to matter for something like this: styling is fairly straightforward with HTML output because you can use CSS. PDF output might require writing Latex (or finding a template where someone else has written Latex), and Word...I don't even know. They all use very different mechanisms to be compiled from Rmarkdown. Shiny creates HTML documents, so it can make use of CSS styling (and I believe usually uses Bootstrap, which is a grid-based framework) – camille Jan 30 '19 at 15:20
  • If you want HTML output, you might try something like [`knitrBootstrap`](https://github.com/jimhester/knitrBootstrap). You can also adjust [chunk options](https://holtzy.github.io/Pimp-my-rmd/#2_figures_in_2_columns). That last link also has an example of adding HTML with Bootstrap classes directly in your Rmarkdown – camille Jan 30 '19 at 15:28
  • 1
    What I am hearing is that HTML is likely the easiest way to go about it. I am fairly agnostic to what output format is actually produced. So if one is more conducive to this than another, than I suppose that is the way to go. –  Jan 30 '19 at 16:20

2 Answers2

4

Here is a workaround for HTML output that automatically decides how many columns are needed. This approach is based on tweaking the chunk hook to alter the markdown output. We basically just perform string operations (search and replace). I hope the comments in the code are clean enough:

MRE:

---
title: "Test File"
output: html_document
---

## R Markdown

```{r, include = F}
library(stringi)
defChunkHook <- knitr::knit_hooks$get("chunk")
knitr::knit_hooks$set(chunk = function(x, options) {
  x <- defChunkHook(x, options)
  if(!is.null(options$multi.col)) {
    x    <- gsub("(\n\`\`\`\n##.*?\`\`\`)", "<div>\\1\n</div>", x)  # wrap div around output chunks
    x    <- gsub("(<img.*?>)", "<div>\\1\n</div>", x)               # wrap div around plots
    ncol <- nrow(stri_locate_all(x, regex = "<div.*?>")[[1]])       # get the number of div elements created
    x    <- gsub("<div>", paste0("<div style=\"width:", 100/ncol,"%;\">"), x)  # add the width to the divs
    x    <- paste0("<div class=\"multi-col\" style=\"display: flex; justify-content: center; align-items: center;\">\n", x, "</div>")  # wrap the mother div around all of the output
  }
  x
})
```

```{r, echo = F, multi.col=T}
summary(cars)
plot(speed ~ dist, cars)
```

```{r, echo = F, multi.col=T}
summary(cars)
plot(speed ~ dist, cars)
plot(mpg ~ hp, mtcars)
```

enter image description here

Martin Schmelzer
  • 23,283
  • 6
  • 73
  • 98
1

Another way to go about this that I have just found is to use gridExtra. You can create your graphics, text objects, tables, etc. and then very cleanly define their structure and relative locations.

https://cran.r-project.org/web/packages/gridExtra/

Pros: Easy to use with a ton of control of a grid. Works great with ggplot2.

Cons: Everything is now an image (including text). Less flexibility in terms of what objects you put into it. No interactivity as far as I can tell.

As a result, I would not want to use this for an HTML object. There are better ways. For a fairly simple, highly controlled use of white space in Word or PDF, this may be a viable approach.