Posted in:

Adding Multi-column Formats to R Markdown Documents

I spent a while looking for a way to display R Markdown content in multiple columns.

I tried inserting alternating HTML and R code blocks, but knitr just seemed to auto close any open HTML element tags, which defeated the purpose.

It is possible to insert script tags inside raw HTML blocks and run your R code from there, but this is kind of nasty and takes the code out of the runnable framework, which is not a good idea where variables are being created/modified and used later on.

For the table/graph example, it is possible to use the position variable as discussed in the previous article.

R Markdown supports some basic HTML elements. It also has its own notation for the <div> tag using the triple colon notation ::: for both opening and closing the element.

Here's a far more generic way of producing the same result so that the two columns can be filled with any producible R Markdown content:

::: {.columns}
::: {.column width="40%"}

contents...

:::
::: {.column width="60%"}

contents...

:::
:::

The columns don't come with any padding or margins, so it's useful to create empty columns as separators.

Here's an example in action using the mtcars R data table, displaying a two column table alongside the accompanying graph:

  • Start off by creating a centred heading using a pair of Markdown ::: DIV tags. Because it's not a true 'Heading' in the document sense of the word, we'll set the font and weight as CSS styles in the div tag directly. Better yet, create a custom figure heading style then only use that throughout your document for consistency.
  • Create a new data set and convert cubic inches to litres for the engine size, and fuel consumption from miles per (US) gallon to litres per 100km.
  • Pass a random 10 rows from that data set into a kable table in the first column and reduce the header font size a little.
  • In the third column, we pass the full data set into a ggplot point graph with smoothing. The plot margin layer just nudges the graph down a little to align with the table.
  • In between is a narrow column with just some white space to ensure it gets rendered in the final HTML document. In this case, I could have just made the two main columns and put a left margin on the plot, but the point of this example is to show a generic layout for any content type.
```{r, warning=FALSE, message=FALSE}
library(ggthemes)
library(kableExtra)
library(ggplot2)
library(dplyr)
data("mtcars")
```
::: {align="center" style="font-size: 150%;font-weight: bold;"}
Engine Size vs Fuel Consumption
:::

::: columns
::: {.column width="35%"}
```{r, echo=FALSE}
metric_cars <- mtcars %>% 
    mutate(
        Engine = round(disp / 61.024, 1),
        Economy = round(100 * 3.785411784 / (1.609344 * mpg), 1)
    ) %>%
    select(Engine, Economy)

metric_cars %>% 
    sample_n(10) %>% 
    kbl(col.names = c('Engine Size (L)', 'Fuel (L/100km)')) %>% 
    kable_styling() %>%
    row_spec(0, font_size=10)
```
:::

::: {.column width="2%"}
&nbsp;
:::

::: {.column width="63%"}
```{r, fig.height=5, fig.width=7, echo=FALSE}
metric_cars %>% 
    ggplot(aes(x=Engine, y=Economy)) +
    geom_point() +
    geom_smooth(formula = y ~ x, method = "loess", color = 'orange') +
    theme_excel_new() +
    theme(
        axis.title = element_text(), 
        plot.margin = margin(1, 0, 0, 0, "cm")
        ) +
    ylab('Fuel Consumption (L/100km)\n') +
    xlab('\nEngine Size (L)') 
```
:::
:::

This will give you the following output:

Producing Multi-column output with R Markdown

If you're using R Studio with the visual editor, you can add columns using Insert > DIV, creating an empty wrapper DIV of class .columns and adding child DIV's with Classes set to .column and width=x% in 'Other'.

Personally, I find this quite fiddly and prone to some 'surprise' behaviour - quicker to type/paste in the code in base view then flip back to visual mode afterwards. You can access all the properties from there:

Working with columns in R Markdown using R Studio visual editor


That's all there is to it - hopefully if you've found this from searching for the answers like I was, you'll find this useful.

Feel free to leave comments below or contact me directly with any questions.

Comments
Sign In to leave a comment.