52

Is it possible to adjust the width of columns when making tables with the kable() function in knitr?

A chunk like this for a table with two columns produces a table that takes up the entire width of the document. I'd like to make the columns narrower. Can this be done with kable() or is another package needed?

This rmarkdown chunk

```{r}
df <- data.frame(x = 1:10,
           y = 11:20)
library(knitr)
kable(df)
```

Produces this table enter image description here

Aligning left with kable(df, align = "l") helps a little but I'd like the two columns adjacent to each other.

Frank
  • 66,179
  • 8
  • 96
  • 180
N Brouwer
  • 4,778
  • 7
  • 30
  • 35

5 Answers5

44

You can try out the kableExtra package.

kable(x, "html") %>%
  kable_styling(full_width = F)
Hao
  • 7,476
  • 1
  • 38
  • 59
  • 1
    this doesnt work for me because it seems that kable_styling does not support document formats provided you use libre office it doesnt work no. i do not know how microsoft office would handle the output though – Dimitrios Zacharatos Jun 06 '19 at 11:07
  • @hao: I am having difficulties to adjust the width in a kableExtra table, which should also include an image, please see here: https://stackoverflow.com/questions/58204272/r-markdown-how-to-create-a-table-with-images-and-text-which-should-be-knitted-a Would you have any advice? – mavericks Oct 02 '19 at 15:08
  • 1
    @Hao great package! I would add this additional part to control the width exactly as you want it. `kable(x, table.attr = "style='width:40%;'" ) %>% kable_classic(full_width = T, position = "center", )` – Ahdee Oct 05 '20 at 20:24
  • This restricts the width of the caption to the width of the resulting table. It would be nice if the two could be decoupled. – passerby51 Dec 29 '22 at 19:00
18

My new favorite thing is the flextable package because 1) the tables are beautiful, 2) you can more easily control things like width and font size, and 3) they render well to HTML and Word. Using your data:

```{r}
library(flextable)
library(magrittr)
df <- data.frame(x = 1:10, y = 11:20)
df %>% regulartable() %>% autofit() %>% 
width(j=~x,width=1) %>% width(j=~y,width=1)
```

With both values of width set to 1, the columns are close together:

flextable-1

If you adjust the last line to width(j=~x,width=2) %>% width(j=~y,width=2) the table looks like this:

flextable-2

mysteRious
  • 4,102
  • 2
  • 16
  • 36
  • According to the [flextable overview vignette](https://cran.r-project.org/web/packages/flextable/vignettes/overview.html), you can also use `df %>% flextable() %>% autofit()`. In case you have an issue installing flextable, make sure you have the libcairo dependency installed at a system level as explained [here](https://stackoverflow.com/a/23649012/2641825) `sudo apt install libcairo2-dev libjpeg-dev libgif-dev`. – Paul Rougieux Aug 31 '20 at 11:11
15

I know it is a long time since my comment. But as @Tjebo pointed out, my comment is worth an answer, I wanted follow his advise. By defining the table format and adding some CSS styling you can change the size of the like so: knitr::kable(x, format = "html", table.attr = "style='width:30%;'"). This may lead to loosing the table lines. kableExtra offer nice styling tools to add for instance lines.

library(knitr)
library(tidyverse)
library(kableExtra)

df <- data.frame(x = 1:10, y = 11:20)

kable(df, format = "html", table.attr = "style='width:30%;'")

kable(df, format = "html", table.attr = "style='width:30%;'") %>% 
  kableExtra::kable_styling()
tjebo
  • 21,977
  • 7
  • 58
  • 94
MarBlo
  • 4,195
  • 1
  • 13
  • 27
2

Another option to fit the table with kableExtra (for me all other optionsdidn't work) package is to use kable_paper( full_width = F)

df <- data.frame(x = 1:10, y = 11:20)    
kbl(dt) %>% kable_paper(full_width = F)    
Imitation
  • 104
  • 7
  • works but applies an entire set of styling include a narrow font: `html_font = "\"Arial Narrow\", arial, helvetica, sans-serif"` – z0lo Dec 21 '22 at 12:30
  • 1
    then you can use kable_classic from the same package like kable_classic(full_width = F, html_font = "Cambria") (or any other required font) – Imitation Dec 22 '22 at 15:49
1

I am new to R but possibly my answer will be useful to other newbies here. Experts, please feel free to correct.

I had a similar issue as the original poster: using kable() my table was off the page and I wanted to rescale. I tried the other answers posted and didn't have success, the reasons may have been that I didn't (at all or properly) install kableExtra or magrittr (the package that allows you to use %>%).

Ultimately, I ended up using latex_options="scale_down", see below:

endpoints <- read.delim("D:/RFiles/GenericName/Endpoints.txt",
            header=TRUE, sep="\t", dec=".")
endpoints_table <- knitr::kable(endpoints,col.names=gsub(" 
                   [.]"," ",names(endpoints)), align="l", 
                   caption = "Endpoints Available")
kable_styling(endpoints_table,latex_options="scale_down",
              "striped") %>%
  row_spec(0,bold=TRUE)
merh-soy
  • 11
  • 2