37

The following code produces 2 tables on top of each other. How would I set it to have them aligned side by side, e.g. 3 to a row?

---
title: "sample"
output: pdf_document
---

```{r global_options, R.options=knitr::opts_chunk$set(warning=FALSE, message=FALSE)}
```   

```{r sample, echo=FALSE, results='asis'}
library(knitr)
t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
print(kable(t1))
print(kable(t2))
```

Output looks like this: enter image description here

Doug Fir
  • 19,971
  • 47
  • 169
  • 299
  • http://tex.stackexchange.com/questions/2832/how-can-i-have-two-tables-side-by-side – RoyalTS Jun 26 '16 at 08:50
  • I saw that while researching how to do this. I do not understand the syntax; The top voted answer says "Just put two tabular environments side by side. Add spacing as desired." then shows some code with syntax like this: \begin{tabular}{ccc}. I don't know how I could apply that to the above example using mtcars tables? – Doug Fir Jun 26 '16 at 09:03

5 Answers5

48

Just put two data frames in a list, e.g.

t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
knitr::kable(list(t1, t2))

Note this requires knitr >= 1.13.

Yihui Xie
  • 28,913
  • 23
  • 193
  • 419
  • Is it possible to use customized lines as with `xtable`? – Alex Jun 26 '16 at 14:31
  • 1
    No, but I think `kable(..., booktabs = TRUE)` and adding `tables: yes` in YAML (as a _top-level_ option) should give you what you want. – Yihui Xie Jun 26 '16 at 14:41
  • This is great! Thanks a lot – Doug Fir Jun 27 '16 at 00:57
  • 11
    Cheeky follow up, would there be an equally simple way to add spacing between the tables? – Doug Fir Jun 27 '16 at 01:06
  • Is there a way to make this work with a Word document. This answer stacks the tables vertically rather than side by side when I tried it (`output: word_document`). – Jean V. Adams Oct 15 '16 at 12:14
  • 2
    @JeanV.Adams No, Word is not supported. – Yihui Xie Oct 16 '16 at 02:58
  • 17
    Is it possible to adjust the spacing between the to tables? – Dambo Mar 24 '17 at 02:33
  • 3
    Interesting to note that when the tables are assigned to objects, and then fed as a list to a single `kable()` call and rendered in a pdf document, the default formatting is different to if the table is printed as the result of the last command of a chunk being `kable()` without assignment. The tables rendered from a list have cells fully outlined, while the tables which were not assigned have partially open cells in the body of the table. – DaveRGP Jan 11 '18 at 15:38
  • 1
    If anyone is finding this approach breaking the $math$ rendering, try adding knitr::kable(escape = False). – shouldsee Feb 07 '18 at 23:23
  • 4
    Although `knitr::kable(list(t1, t2)) %>% kable_styling()` gives no errors, the result is like the entire table was made of a single line. :-( – Paulo S. Abreu Sep 18 '18 at 19:54
  • @YihuiXie When I do this in a R markdown file the table doesn't appear between other writing but just goes to the top of the page. – Dylan Dijk Feb 07 '21 at 12:06
  • Here's a major hack to put space between the tables in LaTeX. Assign the result of `kable()` to a variable, say `foo`. Now `foo[1]` is a character containing the latex (or html) that will be output. You can then manipulate that string. I did `foo[1] <- stringr::str_replace_all(foo[1],"\\\\end\\{tabular\\}","\\\\end{tabular}\\\\hfill")` and the same thing with begin to balance it. Finally, just output `foo` on a line by itself. – turtlegraphics Jun 01 '21 at 06:13
  • the suggestion does not answer the question. the two tables may be unrelated and need different captions etc. – Stephen Mar 10 '23 at 20:21
29

I used this Align two data.frames next to each other with knitr? which shows how to do it in html and this https://tex.stackexchange.com/questions/2832/how-can-i-have-two-tables-side-by-side to align 2 Latex tables next to each other. It seems that you cannot freely adjust the lines of the table as you can do it with xtable (does anybody know more about this?). With format = Latex you get a horizontal line after each row. But the documentation shows two examples for other formats. One using the longtable package (additional argument: longtable = TRUE) and the other using the booktabs package (booktabs = TRUE).

---
title: "sample"
output: pdf_document
header-includes:
- \usepackage{booktabs}
---

```{r global_options, R.options=knitr::opts_chunk$set(warning=FALSE, message=FALSE)}
```


```{r sample, echo=FALSE, results='asis'}
library(knitr)
library(xtable)

t1 <- kable(head(mtcars)[1:3], format = "latex", booktabs = TRUE)
t2 <- kable(head(mtcars)[4:6], format = "latex", booktabs = TRUE)

cat(c("\\begin{table}[!htb]
    \\begin{minipage}{.5\\linewidth}
      \\caption{}
      \\centering",
        t1,
    "\\end{minipage}%
    \\begin{minipage}{.5\\linewidth}
      \\centering
        \\caption{}",
        t2,
    "\\end{minipage} 
\\end{table}"
))  
```

enter image description here

Community
  • 1
  • 1
Alex
  • 4,925
  • 2
  • 32
  • 48
  • 1
    Hi @Alex thanks for answering. I don't recognize the syntax e.g. begin{table}[!htb]. What is that? Is that R? – Doug Fir Jun 27 '16 at 01:08
  • 4
    No that is Latex. If you write in rmarkdown and you are producing a PDF it does not work directly. It is first translated to Latex. The cool thing is that you can also use Latex directly and use its full power. – Alex Jun 27 '16 at 05:01
  • 1
    This is useful code, I have managed to create three rows of tables. Thanks! How would you add a space between the table and caption? Happy to open as a new question, if appropriate. – user2716568 Apr 26 '17 at 09:32
  • 2
    @user2716568 Simply put for example a `\\hspace{-1cm}` between `\\end{minipage}% \\begin{minipage}` (behind the %) if you want reduce the space by 1 cm. And I usually vote for an question or answer if I found it helpful or just interesting. However, this seems not to be common on Stack Overflow ... . – Alex Apr 27 '17 at 17:40
  • 1
    @ Moody_Mudskipper There should be a similar solution. But for this I would ask a new question. – Alex Sep 26 '17 at 18:10
  • 1
    I believe @Alex is using an approach which effectively returns from the R chunk text, which is then processed by LaTeX. This means that if you were to write the following inline: `\begin{table}[!htb] \begin{minipage}{.5\linewidth} \caption{} \centering, \`r t1\`, \end{minipage}% \begin{minipage}{.5\linewidth} \centering \caption{}, \`r t2\`, \end{minipage} \end{table}` is almost functionally equivalent, except that the backticks around `t1` and `t2` are printed out before and after the tables. Any idea how to get around this? – DaveRGP Jan 11 '18 at 16:27
  • I've created a full question here: https://stackoverflow.com/questions/48211887/how-can-the-backticks-printed-around-these-tables-be-escaped – DaveRGP Jan 11 '18 at 16:42
  • I get the error `! LaTeX Error: Not in outer par mode.` when I try to knit to PDF – SantiClaus Jul 07 '18 at 17:02
27

here a solution for html documents

(As this question was asked very broadly and not specifically referring to LaTeX).

Requires knitr and kableExtra

---
title: "Side by side"
output: html_document
---


```{r sample, echo=FALSE}
library(knitr)
library(kableExtra)
t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
```
## as list
```{r}
kable(list(t1, t2))
```

## with float
```{r, echo = FALSE}
kable(t1) %>%
  kable_styling(full_width = FALSE, position = "float_left")
kable(t2) %>%
  kable_styling(full_width = FALSE, position = "left")
```

It is intentional that table t2 gets position = "left". If you allow it to float, this will not block the rest of the paragraph and mess up the following lines in your document.

result:

enter image description here

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • 1
    Any way to control each table width separately when displaying them side by side like you did? – daniellga Jul 20 '20 at 22:08
  • 1
    @daniellga haven't tried it, but check this answer: https://stackoverflow.com/a/61538273/7941188 - if it's useful, please kindly consider upvoting, too :) ( it's not mine!) – tjebo Jul 21 '20 at 08:37
  • 1
    And this would work for either html or pdf document, right? – W7GVR Mar 11 '22 at 14:35
9

In Quarto, you can use layout-ncol. This works both for HTML and PDF outputs.

---
title: "sidebyside"
format: pdf
---

```{r}
#| layout-ncol: 2
#| tbl-cap: "Tables"
#| tbl-subcap: ["A table", "Another table"]

library(knitr)

# table on the left
kable(head(mtcars))

# table on the right
kable(head(cars))
```

enter image description here

Maël
  • 45,206
  • 3
  • 29
  • 67
  • 1
    I somehow had an issue with subcaps on quarto with KableExtra objects. Strangely, putting a label like `#| label: tbl-example` solved the issue. – Matthew Son Feb 23 '23 at 21:59
0

Piggybacking off @Alex's answer since I don't have enough rep to leave a comment:

---
title: "sample"
output: pdf_document
header-includes:
- \usepackage{booktabs}
---

```{r}
library(knitr)
library(xtable)

t1 <- kable(head(mtcars)[1:3], format = "latex", booktabs = TRUE)
t2 <- kable(head(mtcars)[4:6], format = "latex", booktabs = TRUE)
```

\begin{table}[!htb]
  \begin{minipage}{.5\linewidth}
    \centering
```{r}
t1
```
\end{minipage}%
  \begin{minipage}{.5\linewidth}
    \centering
```{r}
t2
```
\end{minipage}%
\end{table}

This will work instead of the cat() function call. In my experience, outputting LaTeX code from a code chunk will just lead to it getting printed as plain text in the PDF.