longtable= T messes up with scaled down table in r markdown pdf - r

I have a table in my r markdown pdf.
kable(df, "latex", longtable = F, booktabs = T) %>%
kable_styling(latex_options = c("hold_position",
"scale_down"),
fixed_thead = T)
this give a nice table centered in the page, but it is too long for the height of the page. so I added
kable(df, "latex", longtable = T, booktabs = T) %>%
kable_styling(latex_options = c("repeat_header"))
as suggested by many posts. My table now is split across several pages but now wider so that it does not fit within the width of the paper.
How can I keep the original width while still using longtable.
I run the same code suggested here enter link description here
but my table exceeds the width of the paper.

It seems like it is not possible to resize the table when using Longtable = T. When you run this code:
```{r}
library(kableExtra)
kable(iris, "latex", longtable = T, booktabs = T) %>%
kable_styling(latex_options = c("repeat_header", "scale_down"))
```
You get the following warning when trying: Warning in styling_latex_scale_down(out, table_info): Longtable cannot be resized.
Output:
When you add the command full_width = T to the kable_styling, it looks more scaled than before. Check this output:

You could try using kable_styling( full_width = TRUE) which fits a wide (10 column version of iris data across one page). You may need to tweek the column headings so they are legible. Without seeing your actual data it's difficult to suggest anything else.
Update: 2022-06-05 since R version 4.1.3 (2022-03-10) and RStudio 2022.02.3+492 this solution produces an error:
! Dimension too large.
\LT#max#sel #1#2->{\ifdim #2=\wd \tw#
#1\else \number \c#LT#chunks \fi }{\th...
l.328 \end{longtabu}
---
output:
pdf_document
---
```{r}
library(kableExtra)
cbind(iris, iris) |>
kbl("latex", longtable = T, booktabs = T) %>%
kable_styling(latex_options = c("repeat_header"), full_width = TRUE)
```

As Peter said, kable(..., longtable = TRUE) and kable_styling(..., full_witdh = TRUE) no longer work with R version >= 4.1.3 (2022-03-10) and RStudio 2022.02.3+492.
After (many) hours of trial and error with kable and kableExtra, the only solution I found uses pander. It doesn't explicitly control the width of the table, but the result looks good with Peter's example.
---
output:
pdf_document
---
```{r}
library(pander)
cbind(iris, iris) |>
pander("This is a Table")

Related

How to set Multicolumn width (longtable latex) on Rmarkdown

I am having some issues with a table built on Rmarkdown to PDF output.
I am using gtsummary to summarise stratified data, then using to_kable_extra in order for export to PDF.
My code looks like this
title: "Untitled"
output:
pdf_document:
keep_tex: yes
date: "2022-08-17"
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(gtsummary)
library(kableExtra)
library(dplyr)
```
```{r}
data <- data.frame(id = rep(1:3), Age = c(20,20,25),Area = letters[1:3])
data %>%select(-id) %>%tbl_strata(strata = Area, .tbl_fun = ~.x %>% tbl_summary(missing = 'no'))%>%
as_kable_extra(
booktabs = TRUE,
longtable = TRUE,
linesep = ""
) %>%
kableExtra::kable_styling(
position = "left",
latex_options = c("striped", "repeat_header"),
stripe_color = "gray!15"
)%>% column_spec(column = 1:4, width = '4cm')
```
The problem comes on the Latex output, with "column_spec" on R i can set latex columns width without issue.
However the multicolumns created for the stratified data I can not from R set their width, and that is my question. How can I achieve this without having to edit the .tex file by myself everytime I want to get this report done.
This is a piece of the Latex file, instead of what is actually happening : \multicolumn{1}{c}{\textbf{a}}; I need it to be \multicolumn{1}{p{4cm}}{\textbf{a}}
\begin{longtable}[l]{>{\raggedright\arraybackslash}p{4cm}>
{\centering\arraybackslash}p{4cm}>{\centering\arraybackslash}p{4cm}>
{\centering\arraybackslash}p{4cm}}
\toprule
\multicolumn{1}{c}{ } & \multicolumn{1}{c}{\textbf{a}} & \multicolumn{1}{c}{\textbf{b}}
& \multicolumn{1}{c}{\textbf{c}} \\
Another possible solution for me would be to turn this multicolumns information to a regular row record susceptible to general column width.

How to handle the overlay of kable output with page number?

I use kbl() function, in a rnw file that I compile in a pdf with knitr, to make a table starting from a dataframe. I use kableExtra option scale_down to adapt the table size to page size. It works fine but the table overlay with the page number of my pdf output. I'd like to know what's the best way to handle this type of problem. Thanks in advance for the help.
You could add some Latex code that puts the tabular environment into a box and resizes the content. Below is an example using \resizebox
Here's tab, a LaTex table with Gaussian random numbers generated by kable:
```{r, message = F, warning=F}
library(knitr)
library(tidyverse)
library(kableExtra)
ncol <- 10
nrow <- 30
df <- map_dfc(1:ncol, ~ data.frame(round(rnorm(nrow), 2))) %>%
set_names(letters[1:ncol])
tab <- kbl(df, format = "latex")
```
And here's how to resize it by text height/width using resizebox (see this post on tex.stackexchange for details on how the scaling works)
```{r, results='asis'}
cat(
"\\begin{table}
\\centering
\\resizebox*{\\textwidth}{\\dimexpr\\textheight-2\\baselineskip\\relax}{%",
tab,
"\n}
\\end{table}"
)
```
Result for the 30x10 table
Let's double rows and columns (ncol <- 20; nrow <- 60)
Result for 60x20 table.
I have three suggestions. The first one is maybe set your table to the next page using \newpage in your Rmarkdown code which is latex code. The second option is maybe set latex_options="HOLD_position" in your Kable_styling function. This will set the table at a certain place which maybe could help your problem. The third option is using 'longtable = TRUE` which means that the table continues on the next page. Here is the code for option one and two with:
```{r}
library(knitr)
library(tidyverse)
library(kableExtra)
df <- data.frame(x = 1:10, y = 11:20)
kable(df) %>%
kable_styling(latex_options = "HOLD_position")
```
\newpage
```{r}
kable(df) %>%
kable_styling(latex_options = "HOLD_position")
```
Which looks like this:
Here is the code for option three:
```{r}
library(tidyverse)
library(knitr)
library(kableExtra)
df <- data.frame(x = 1:50, y = 11:60)
kable(df, "latex", longtable = T, booktabs = T) %>%
kable_styling(latex_options = c("repeat_header"), font_size = 7)
```
Looks like this:

Pass custom function to RMarkdown YAML df_print for printing dataframes when knitting HTML output

This is my very first posting on Stack Overflow, so please forgive me if this is an ill-formed or non-reproducible question. I am attempting to pass the following custom data table printing function ('print.me') to the YAML header in RMarkdown for df_print knitting to HTML:
print.me <- function(x) {
x <- x %>% kbl(digits=2, align= 'l', booktabs=T) %>%
kable_styling(fixed_thead = T, position ="float_right") %>%
kable_paper("striped", full_width = T, fixed_thead = T,
html_font = "Helvetica", font_size = 11) %>%
row_spec(0, color = "yellow", background = "#5b705f", font_size = 12) %>%
scroll_box(width = "700px", height = "300px")
return(x)
}
This function successfully renders the dataframe format I am hoping for when printing mtcars from RMarkdown:
The problem is that I cannot figure out a way to successfully pass 'print.me' to the YAML header so that 'print.me' becomes the default method of rendering dataframes when knitting to HTML. My code in the YAML header looks like:
df_print: !expr 'print.me'
However, I receive the following error message:
Error: object 'print.me' not found
Error in yaml::yaml.load(..., eval.expr = TRUE) :
Could not evaluate expression: print.me
Calls: ... parse_yaml_front_matter -> yaml_load ->
Execution halted
The df_print documentation claims that it is possible to pass an arbitrary function to df_print, and I have found a past post that seems to have reached a workaround, but I cannot for the life of me figure out how to call this function from the header. Thanks for any help! ~ Jamie
I couldn't find this in the rmarkdown documentation but I don't think it's recommended to pass a complex function like yours to the df_print argument in the YAML header. However, according to this issue on GitHub for (a simplified version of) print.me() it goes like this:
---
title: "testprint"
output:
html_document:
df_print: !expr print.me <- function(x, ...) { knitr::asis_output(kableExtra::kbl(x, digits=2, align= 'l'))}
---
Instead, you may register your own method for printing dataframes in a code chunk (preferably right after the YAML header) like this:
```{r setup, include=FALSE}
library(kableExtra)
library(knitr)
print.me <- function(x, ...) {
x %>%
kbl(digits=2, align= 'l', booktabs=T) %>%
kable_styling(fixed_thead = T, position ="float_right") %>%
kable_paper("striped", full_width = T, fixed_thead = T,
html_font = "Helvetica", font_size = 11) %>%
row_spec(0, color = "yellow", background = "#5b705f", font_size = 12) %>%
scroll_box(width = "700px", height = "300px") %>%
asis_output()
}
registerS3method("knit_print", "data.frame", print.me)
```
The technical details are a bit complicated. In short, we overwrite the default function that is called upon checking the class of the object to be printed (geeks call this procedure method dispatch) with the custom function and register this method to knitr.

Rotating a table in PDF output from RMarkdown with more than one page

I want to rotate a wide table in my PDF output. I came across this fantastic question, but my table is longer.
When I copy/paste one of the examples shown in that question, it works nice using RMarkdown.
library(kableExtra)
kable(iris[1:5,],
format = "latex", booktabs = TRUE) %>%
kableExtra::landscape()
However, if we remove the subsetting we see that the table exceeds the dimension of the page.
library(kableExtra)
kable(iris,
format = "latex", booktabs = TRUE) %>%
kableExtra::landscape()
So my question is very simple: how can we create as many PDF pages as needed by splitting the table in parts?
Can you try this (sorry I can't comment) :
dt <- iris
kable(dt, "latex", longtable = T, caption = "title") %>%
kable_styling(font_size = 7, latex_options = c("repeat_header"),repeat_header_text = "",
full_width = F) %>% kableExtra::landscape()
This seems to work for me.
Here's the result : pdf output
Is it what you want?

Rendering Table with conditional color in latex as a pdf document with rownames = TRUE (rmarkdown, kable and kableExtra )

I am attempting to output a latex table using r markdown, kable and kableExtra. When i use the option row.names=FALSE instead of row.names=TRUE the latex code generates \vphantom code which produce an error to create the pdf .
It seems the problem is linked to the row_spec option.
Here is Rmarkdown code (.Rmd File):
---
title: "Test"
output:
pdf_document:
fig_caption: true
keep_tex: true
---
{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
{r}
library(knitr)
library(kableExtra)
temp <- mtcars[1:5,1:5]
kable(temp, format = "latex", booktabs = F,row.names=F) %>%
kable_styling(position = "center") %>%
row_spec(1, bold = T, background = "red")
The error is :
! Forbidden control sequence found while scanning use of
\check#nocorr#.
\par l.105 ...color{red} \textbf{21.0 &\vphantom{1} 6}
& \textbf{160} & \textbf{...
Do you have any issue of what is happening ?
This is caused by the duplicated rows in the dataframe, as both rows 1 and 2 are the same.
Reviewing the code for row_spec_latex, when kableExtra is used against a kable table, it checks for duplicated rows. If it finds one, it inserts the vphantom argument within the fix_duplicated_rows_latex internal function. This vphantom insertion is then messing up the formatting of the textbf function.
This seems like a slight bug, so it may be worth reporting it as an issue in kableExtra: https://github.com/haozhu233/kableExtra . I am sure that the vphantom is added for a good reason though, but doubt this was an intended consequence.
Supporting code:
---
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)
temp <- mtcars[1:5,1:5]
```
```{r}
# Keeping the row names (means all rows are unique)
kable(temp, format = "latex", booktabs = F) %>%
kable_styling(position = "center") %>%
row_spec(1, bold = T, color = "red")
```
```{r}
# Highlighting second row (which doesn't have the vphantom statement)
kable(temp, format = "latex", booktabs = F, row.names=F) %>%
kable_styling(position = "center") %>%
row_spec(2, bold = T, color = "red")
```

Resources