13

How can I wrap a cell in a knitr::kable table cell using \n?


I want to generate a .rmd file containing some tables where one column needs text wrapping. The places where the wrapping should occur are marked with \n. I tried (this is a standalone .rmd document):

---
output: pdf_document
---

## A Table with text wrap

```{r cars}
knitr::kable(data.frame(col1 = c("a", "b"), col2 = c("one\ntwo", "three\nfour")))
```

..but this doesn't work. Instead of staying in col2, the wrapped part lives on the next line of col1.

enter image description here

Expected output is:

col1 | col2
-------------
a    | one
     | two
b    | three
     | four

Solutions using other packages than knitr are welcome as long as they allow to print (nearly) as nice.

symbolrush
  • 7,123
  • 1
  • 39
  • 67

2 Answers2

9

A fire-and-forget solution for flexible dual HTML/PDF of standard tables. It incorporates kableExtra's linebreak function outlined by @snoram.
Assumption: You use <br> as your line break indicator.

```{r}
knit_table(df1)
```

image

Code

library(dplyr)
library(knitr)
library(kableExtra)

knit_table <- function(df){
  if (is_html_output()) {
    df %>%
      kable("html", escape = F) %>%
      kable_styling()
  } else {
    df <- data.frame(lapply(df, function(x) {gsub("<br>", "\n", x)}), stringsAsFactors = F)

    df %>%  
      mutate_all(linebreak) %>%
      kable("latex", booktabs = T, escape = F)  
  }
}

Data

df1 <- data.frame(col1 = c("a", "b"),
                  col2 = c("one<br>two", "three<br>four"))
Roman
  • 4,744
  • 2
  • 16
  • 58
  • 2
    Thanks @Roman for this extremely simple solution. It is exactly what I was searching for, since the \n's were a choice I can easily change to
    . This however only works for html output, at least for me. Does it also work for pdf output for you?
    – symbolrush Oct 23 '18 at 09:48
  • You both are absolutely right. I adapted the approach for dual-use. – Roman Oct 23 '18 at 18:27
8

If you don't mind using kableExtra you can definitely achieve this, here is one example:

library(kableExtra)
knitr::kable(data.frame(col1 = c("a", "b"), col2 = linebreak(c("one\ntwo", "three\nfour"))),
             escape = FALSE)

enter image description here

More details here.

s_baldur
  • 29,441
  • 4
  • 36
  • 69
  • Thanks. Unfortunately, this throws an error for me: `Error in linebreak(c("one\ntwo", "three\nfour")) : could not find function "linebreak"`. What package does the `linebreak` function come from? – symbolrush Oct 23 '18 at 08:47
  • `kableExtra`, you first need to install and then add library(kableExtra) to your script... – s_baldur Oct 23 '18 at 08:48
  • Thanks, @snoram. I unfortunately had an old version of kableExtra installed. Changed that. Now the code runs. For pdf output it works perfectly, for html output it produces an empty `col2`. Does it also work for html output for you? – symbolrush Oct 23 '18 at 09:50
  • I just checked and it doesn't work in `html`. So instead you could use Roman's solution or open a new question if it is important to have one solution that works for both. – s_baldur Oct 23 '18 at 11:27