Dearest,

This is similar to one script I have been running for months on my platform.

I have some long text inside a column (called "description") and I want to wrap it (no more than 20 characters per line). In order to do this, I have a function which inserts a break line "\n" in the text whenever needed. I then use kableextra's "linebreak" function on that text to make sure the linebreak is properly understood (and it is).

The final result is then processed via latex to generate a pdf. The trouble is that the text inside the description column, although broken as I want, is no longer left aligned. I am sure I have not had this in the past (before updating R to 4.0.3 and reinstalling kableextra).

Anyone who knows how to fix this will have my gratitude!

Thanks

library(tidyverse)
library(kableExtra)
#> 
#> Attaching package: 'kableExtra'
#> The following object is masked from 'package:dplyr':
#> 
#>     group_rows
library(formattable)




##Functions to wrap and format text in the table



wrapper2 <- function(x, width) {
    lapply(strwrap(x, width = width, simplify = FALSE), paste, collapse="\n")
    
}


wrapper_text <- function(x, width) {
 res <- wrapper2(x, width) %>% unlist
    return(res)
}







df <- structure(list(description = c("Total Goods", "85 Electrical machinery and equipment", 
"84 Machinery and mechanical appliances", "63 Other made-up textile articles", 
"94 Furniture; lamps and lighting fittings", "90 Optical, medical or surgical instruments", 
"62 Apparel and clothing, not knitted or crocheted", "29 Organic chemicals", 
"39 Plastics", "95 Toys, games and sports requisites", "87 Motor vehicles"
), y = c(8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8)), row.names = c(NA, 
-11L), class = c("tbl_df", "tbl", "data.frame"))

df2 <-  df  %>%
    mutate(description=wrapper_text(description, 20))  %>%
    mutate(description=linebreak(description))


mytable <- df2 %>%
     kable("latex", booktabs = T, escape = F,align=c("l", "r")) %>%
 
    kable_styling( ) 




writeLines(
  c(

      "\\documentclass{article}",
      "\\usepackage{graphicx}",
      "\\usepackage{makecell}",
"\\usepackage{float}",
          "\\usepackage{booktabs}",
"\\begin{document}",
"\\pagestyle{empty}",
    mytable,
    "\\end{document}"
  ),
  "test_table.tex"
)





tools::texi2pdf("test_table.tex", clean = TRUE)


print(sessionInfo())
#> R version 4.0.3 (2020-10-10)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Debian GNU/Linux 10 (buster)
#> 
#> Matrix products: default
#> BLAS:   /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.3.5.so
#> 
#> locale:
#>  [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8    
#>  [5] LC_MONETARY=en_GB.UTF-8    LC_MESSAGES=en_GB.UTF-8   
#>  [7] LC_PAPER=en_GB.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C       
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#>  [1] formattable_0.2.0.1 kableExtra_1.2.1    forcats_0.5.0      
#>  [4] stringr_1.4.0       dplyr_1.0.2         purrr_0.3.4        
#>  [7] readr_1.4.0         tidyr_1.1.2         tibble_3.0.3       
#> [10] ggplot2_3.3.2       tidyverse_1.3.0    
#> 
#> loaded via a namespace (and not attached):
#>  [1] styler_1.3.2      tidyselect_1.1.0  xfun_0.18         haven_2.3.1      
#>  [5] colorspace_1.4-1  vctrs_0.3.4       generics_0.0.2    viridisLite_0.3.0
#>  [9] htmltools_0.5.0   yaml_2.2.1        blob_1.2.1        rlang_0.4.8      
#> [13] pillar_1.4.6      glue_1.4.2        withr_2.3.0       DBI_1.1.0        
#> [17] dbplyr_1.4.4      modelr_0.1.8      readxl_1.3.1      lifecycle_0.2.0  
#> [21] munsell_0.5.0     gtable_0.3.0      cellranger_1.1.0  rvest_0.3.6      
#> [25] htmlwidgets_1.5.2 evaluate_0.14     knitr_1.30        fansi_0.4.1      
#> [29] highr_0.8         broom_0.7.1       Rcpp_1.0.5        scales_1.1.1     
#> [33] backports_1.1.10  webshot_0.5.2     jsonlite_1.7.1    fs_1.5.0         
#> [37] hms_0.5.3         digest_0.6.25     stringi_1.5.3     grid_4.0.3       
#> [41] cli_2.0.2         tools_4.0.3       magrittr_1.5      crayon_1.3.4     
#> [45] pkgconfig_2.0.3   ellipsis_0.3.1    xml2_1.3.2        reprex_0.3.0.9001
#> [49] lubridate_1.7.9   assertthat_0.2.1  rmarkdown_2.4     httr_1.4.2       
#> [53] rstudioapi_0.11   R6_2.4.1          compiler_4.0.3

Created on 2020-10-13 by the reprex package (v0.3.0.9001)

1

There are 1 best solutions below

4
On BEST ANSWER

The problem seems to come from your wrapper functions rather than kableExtra. If you inspect your df2 data.frame, you'll see that it includes a lot of \makecell calls with weird alignment.

These makecells are inserted by the kableExtra::linebreak function. To get the behavior you want, change your wrapper function with this:

linebreak(description, align='l')

This change of behavior was introduced in a recent commit to the kableExtra repository.

For reference, I think that a more idiomatic (and easier) way to use kableExtra in this context would be to avoid wrapping text yourself, and to specify a column width using the column_spec function.

Note that I use the df frame specifically, rather than go through the df2 like you did:

library(kableExtra)

mytable <- df %>% 
  kbl("latex", booktabs=TRUE, escape=FALSE, align="lr") %>%
  kable_styling() %>%
  column_spec(1, width="2in")

writeLines(c(
  "\\documentclass{article}",
  "\\usepackage{graphicx}",
  "\\usepackage{makecell}",
  "\\usepackage{float}",
  "\\usepackage{booktabs}",
  "\\begin{document}",
  "\\pagestyle{empty}",
  mytable,
  "\\end{document}"),
  "test_table.tex"
)
tools::texi2pdf("test_table.tex", clean = TRUE)

This produces a document with this table:

enter image description here