Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I split a table so that it appears side by side in R markdown?

Tags:

r-markdown

I'm writing a document with R markdown and I'd like to put a table. The problem is that this table only has two columns and takes a full page, which is not very beautiful. So my question is : is there a way to split this table in two and to place the two "sub-tables" side by side with only one caption ?

I use the kable command and I tried this solution (How to split kable over multiple columns?) but I could not do the cbind() command.

Here's my code to create the table :

---
title: 
author: 
date: "`r format(Sys.time(), '%d %B, %Y')`"
output: pdf_document
indent: true
header-includes:
  - \usepackage{indentfirst}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

```{r, echo = FALSE}
kable(aerop2, format = "markdown")
```

where aerop2 is my data frame with a list of country names in column 1 and the number of airports in each of these countries in column 2.

I have a long two-column table which is a waste of space. I would like to split this table in two sub-tables and put these sub-tables side by side with a caption that includes both of them.

like image 437
bretauv Avatar asked Jun 04 '19 13:06

bretauv


2 Answers

This doesn't give a lot of flexibility in spacing, but here's one way to do it. I'm using the mtcars dataset as an example because I don't have aerop2.

---
output: pdf_document
indent: true
header-includes:
  - \usepackage{indentfirst}
  - \usepackage{booktabs}
---

```{r setup, include=FALSE}
library(knitr)
opts_chunk$set(echo = TRUE)
```

The data are in Table \ref{tab:tables}, which will float to the top of the page.

```{r echo = FALSE}
rows <- seq_len(nrow(mtcars) %/% 2)
kable(list(mtcars[rows,1:2],  
           matrix(numeric(), nrow=0, ncol=1),
           mtcars[-rows, 1:2]), 
      caption = "This is the caption.",
      label = "tables", format = "latex", booktabs = TRUE) 
```

This gives:

screenshot

Note that without that zero-row matrix, the two parts are closer together. To increase the spacing more, put extra copies of the zero-row matrix into the list.

like image 183
user2554330 Avatar answered Oct 08 '22 20:10

user2554330


The solution offered by 'user2554330' was very useful.
As I needed to split in more columns and eventually more sections, I further developed the idea. I also needed to have the tables after the text, not floating to the top. I found a way using kableExtra::kable_styling(latex_options = "hold_position"). I am writing here to share the development and to ask minor questions.
1 - Why did you add the line - \usepackage{indentfirst}?
2 - What is the effect of label = "tables" as kable() input?
(The questions are related to Latex. I probably know to little to understand the explanation in kable() documentation: "label - The table reference label"!)

---
title: "Test-split.print"
header-includes:
  - \usepackage{booktabs}
output:
  pdf_document: default
  html_document:
    df_print: paged
---

```{r setup, include=FALSE}
suppressPackageStartupMessages(library(tidyverse))
library(knitr)
library(kableExtra)

split.print <- function(x, cols = 2, sects = 1, spaces = 1, caption = "", label = ""){
  if (cols < 1) stop("cols must be GT 1!")
  if (sects < 1) stop("sects must be GT 1!")
  rims <- nrow(x) %% sects
  nris <- (rep(nrow(x) %/% sects, sects) + c(rep(1, rims), rep(0, sects-rims))) %>%
    cumsum() %>% 
    c(0, .)
  
  for(s in 1:sects){
    xs <- x[(nris[s]+1):nris[s+1], ]
    rimc <- nrow(xs) %% cols
    nric <- (rep(nrow(xs) %/% cols, cols) + c(rep(1, rimc), rep(0, cols-rimc))) %>%
      cumsum() %>% 
      c(0, .)
    lst <- NULL
    spc <- NULL
    for(sp in 1:spaces) spc <- c(spc, list(matrix(numeric(), nrow=0, ncol=1)))
    for(c in 1:cols){
      lst <- c(lst, list(xs[(nric[c]+1):nric[c+1], ]))
      if (cols > 1 & c < cols) lst <- c(lst, spc)
    }
    kable(lst, 
          caption = ifelse(sects == 1, caption, paste0(caption, " (", s, "/", sects, ")")),
          label = "tables", format = "latex", booktabs = TRUE) %>% 
      kable_styling(latex_options = "hold_position") %>% 
      print()
  }
}
```

```{r, results='asis'}
airquality %>% 
  select(1:3) %>% 
  split.print(cols = 3, sects = 2, caption = "multi page table")
```
like image 36
Roberto Scotti Avatar answered Oct 08 '22 21:10

Roberto Scotti