1

I have an Rmarkdown document with embedded tables but I have trouble understanding the underlying rules for text wrapping and hyphenation for the table contents. Searching through stackoverflow and other resources hasn't provided a lot of insight.

An example is provided below, the columns widths specified are only necessary in the example to reproduce the problem I have with the real table. After some trial and error, I was able to get the last column header to hyphenate by entering it as " Manufacturer " but this trick does not work in the rows below that header. Additional examples of problems with text in cells either getting cut off or spilling into adjacent cells are shown in the third column (Result) and the formatting of cell entries is displayed in the second column. I've added a border between the third and fourth columns to highlight the problems. The real table has 8 columns and I've adjusted those column widths as much as possible while preserving readability.

---
title: 'Table_7_problem'
fontsize: 11pt
output:
  bookdown::pdf_document2:
   toc: false
   number_sections: false 
   latex_engine: xelatex
tables: yes
header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{colortbl} # to set row stripe colors
- \usepackage{tabu}
- \setlength{\tabcolsep}{1pt} 
---
```

```{r setup, echo = TRUE, cache = FALSE, warning = FALSE, message = FALSE}
{r setup, echo = FALSE, cache = FALSE, warning = FALSE, message = FALSE}

library(knitr)

```

# Table 7: Appliance durability

This table contains fictional data.

```{r table7, echo = FALSE, cache = FALSE, warning = FALSE, message = FALSE}
{r table7, echo = FALSE, cache = FALSE, warning = FALSE, message = FALSE}

table7 <- data.frame(
  Column_1 = c('Very long string #1 that requires a wide column to accomodate and maintain readability' ,'Very long string #2... and more of the same down rows for this column...','Very long string #3','Very long string #4','Very long string #5','Very long string #6', 'Very long string #7'),
  Column_2 = c('"SampleText"',
               '"Sample Text"',
               '" SampleText"',
               '"SampleText "',
               '" SampleText "',
               '"SampleText #2"',
               '"Sample Text #2"'),
  Column_3 = c('SampleText',
               'Sample Text',
               ' SampleText',
               'SampleText ',
               ' SampleText ',
               'SampleText #2',
               'Sample Text #2"'),
  Column_4 = c('Manufacturer', 
               ' Manufacturer', 
               'Manufacturer ',
               ' Manufacturer ',
               ' LongManufacturerName',
               'Long_Manufacturer_Name',
               "Long Manufacturer Name")
)

###

colnames(table7) <- c("Name", "Cell Content Format", "Result", " Manufacturer ")

library(kableExtra)

  table7 %>% 
  kbl(longtable = TRUE, align = "lllc", booktabs = TRUE) %>% 
  kable_styling(full_width = FALSE, font_size = 8, latex_options = c("repeat_header", "striped"), stripe_color = "gray!15", repeat_header_text = "Table 7 \\textit{continued...}") %>%
  row_spec(0, bold = TRUE) %>% 
  column_spec(1, width = "1.5in") %>%
  column_spec(2, width = "3.825in") %>%
  column_spec(3, width = "0.5in") %>%
  column_spec(4, width = "0.45in", border_left = TRUE)
```

The above code produces this:

enter image description here

Any advice or solutions on how to control the hyphenation and word wrapping to resolve these problems?

*** UPDATE 2022-09-07

Updating the status - I've explored several packages for making the table and so far none will do everything I was looking for but, for me, it seems the flextable package will do most of what I wanted. The updated code and pdf result are shown below. It may not be pretty but it gets the job done. Seems some conflicts arise when piping the formatting commands but they seem to work just fine if entered one at a time, which is why there are multiple t7 <-... statements (I played around with much more elaborate formatting and the same strategy of using individual statements worked).


table7 <- data.frame(
  Column_1 = c('Very long string #1 that requires a wide column to accomodate and maintain readability' ,'Very long string #2... and more of the same down rows for this column...','Very long string #3','Very long string #4','Very long string #5','Very long string #6', 'Very long string #7'),
  Column_2 = c('"SampleText"',
               '"Sample Text"',
               '" SampleText"',
               '"SampleText "',
               '" SampleText "',
               '"SampleText #2"',
               '"Sample Text #2"'),
  Column_3 = c('SampleText',
               'Sample Text',
               ' SampleText',
               'SampleText ',
               ' SampleText ',
               'SampleText #2',
               'Sample Text #2"'),
  Column_4 = c('Manufacturer', 
               ' Manufacturer', 
               'Manufacturer ',
               ' Manufacturer ',
               ' LongManufacturerName',
               'Long_Manufacturer_Name',
               "Long Manufacturer Name")
)

###

colnames(table7) <- c("Name", "Cell Content Format", "Result", "Manu-\nfacturer")

library(flextable)
library(stringr)

set_flextable_defaults(
  font.family = gdtools::match_family(font = "Serif"), 
  font.size = 8,
  padding = 3)

table7$`Manu-\nfacturer` <- str_replace(string = table7$`Manu-\nfacturer`, pattern = 'Manufacturer', replacement = 'Manu-\nfacturer')

t7 <- table7 %>% flextable() %>% 
  width(., width = c(1.5, 3.825, 0.5, 0.45), unit = "in") %>% 
  #add_header_lines(., values = "Table 7") %>% 
  theme_zebra(.)

t7 <- hline(t7, i = 1, border = officer::fp_border(color = "black"), part = "header")
t7 <- flextable::align(t7, i = 1, j = 1, align = "left", part = "header")

t7

the above generates the figure below. The str_replace strategy suggested by @Julian achieves the hyphenation and wrapping and theme_zebra() in flextable preserved the row striping.

enter image description here

user3900349
  • 55
  • 1
  • 5

1 Answers1

1

What you can do is to add linebreaks and add escape = FALSE to your kable function. Note that you need to escape #,_ etc. as well.

table7 <- data.frame(
  Column_1 = c('Very long string 1 that requires a wide column to accomodate and maintain readability' ,'Very long string 2... and more of the same down rows for this column...','Very long string 3','Very long string 4','Very long string 5','Very long string 6', 'Very long string 7'),
  Column_2 = c('"SampleText"',
               '"Sample Text"',
               '" SampleText"',
               '"SampleText "',
               '" SampleText "',
               '"SampleText 2"',
               '"Sample Text 2"'),
  Column_3 = c('Sample\nText',
               'Sample\n Text',
               ' Sample\nText',
               'Sample\nText ',
               ' Sample\nText ',
               'Sample\nText 2',
               'Sample \nText 2"'),
  Column_4 = c('Manu\nfacturer', 
               ' Manu\nfacturer', 
               'Manu\nfacturer ',
               ' Manu\nfacturer ',
               ' Long\nManufacturer\nName',
               'Long\nManufacturer\nName',
               "Long\n Manufacturer\n Name")
)

kable_example

Julian
  • 6,586
  • 2
  • 9
  • 33
  • Thanks (sorry for the delayed reply - bit of cyber holiday). I'll give this a try. The table is populated by reading in data from a very large database rather than manual entry. – user3900349 Sep 05 '22 at 14:42
  • 1
    You can try to automatize it using https://stackoverflow.com/questions/57044895/insert-a-character-at-every-nth-instance-in-r – Julian Sep 06 '22 at 07:05
  • Thanks for the suggestion and link. I think some combination of these answers will do the trick. I do find it curious that the formatting that works for the column header has no effect for the cell contents within that column. – user3900349 Sep 06 '22 at 12:14
  • I'm making a bit of progress here but there's another problem also shown in the answer from @Julian which is: the row striping becomes inconsistent/ disappears when linebreaks are inserted... – user3900349 Sep 06 '22 at 18:34
  • You could turn off row striping if that’s an option for you. – Julian Sep 06 '22 at 19:36