0

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)

larry77
  • 1,309
  • 14
  • 29
  • I see that you simultaneously opened an issue on the kableExtra github. Could you tell us specifically what "broken" means? Could you simplify the example? Try removing commands one by one until the problem no longer appears. This will tell you which of the commands, in particular, causes the problem. With this [Minimal Reproducible Example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) in hand, we can then help you find the problem. Also, this might depend on the rest of yrou LaTeX document. So provide a truly minimal example of that too. – Vincent Oct 13 '20 at 11:01
  • 1
    I simplified and clarified the post. If I knew how to make the problem disappear by removing line by line, I would not be posting now. However, point taken about a leaner post. – larry77 Oct 13 '20 at 14:45

1 Answers1

1

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

Vincent
  • 15,809
  • 7
  • 37
  • 39
  • I suppose I will soon accept this as an answer -- thanks . I still puzzles me that I.have been able to use my wrapper for months without a glitch. – larry77 Oct 14 '20 at 06:44
  • Ha! I think I found something! Try this in the last line of your `wrapper2` function: `linebreak(description, align="l")`. Looks like there was a change to the `align` parameter a few months ago: https://github.com/haozhu233/kableExtra/commit/c79c5a83dc8b18398f66d3b1262b39a025fe4719#diff-7557bd90b4cae7ae601e878db504e3e3e4ff4c654a311d1badf724975014f430 – Vincent Oct 14 '20 at 11:06
  • 1
    OK! This is really the answer I was looking for and the reason why the code did not work like in the past. The new default looks like madness to me, but at least I know what happened. I will mark your previous suggestion as an answer, but it is really your comment which did it for me. Thanks. – larry77 Oct 14 '20 at 13:13
  • cool, I edited my answer to include the `linebreak` discussion. – Vincent Oct 14 '20 at 13:34