gt
gt copied to clipboard
Preserve `caption` of <gt_tbl> object when generating LaTeX code with `gt::as_latex()`
Prework
- [x] Read and abide by gt's code of conduct and contributing guidelines.
- [x] Search for duplicates among the existing issues (both open and closed).
Proposal
gt::as_latex()
drops the caption in the gt_tbl
object:
dt <- mtcars[1:2, 1:2]
gt::gt(data = dt, caption = "mtcars data") |>
gt::as_latex() |>
as.character()
#> [1] "\\begin{longtable}{rr}\n\\toprule\nmpg & cyl \\\\ \n\\midrule\\addlinespace[2.5pt]\n21 & 6 \\\\ \n21 & 6 \\\\ \n\\bottomrule\n\\end{longtable}\n"
gt::gt(data = dt) |>
gt::tab_caption("mtcars data") |>
gt::as_latex() |>
as.character()
#> [1] "\\begin{longtable}{rr}\n\\toprule\nmpg & cyl \\\\ \n\\midrule\\addlinespace[2.5pt]\n21 & 6 \\\\ \n21 & 6 \\\\ \n\\bottomrule\n\\end{longtable}\n"
As can be seen in the output, there is no \caption{}
command in the LaTeX code that is generated. This is an issue because my workflow is saving the generated LaTeX code string to a file and then calling \input{}
on that file in LaTeX, and then I end up getting a table with no captions. This also prevents cross-referencing tables in PDF documents generated using Rmarkdown or Quarto.
Interestingly enough, when the title
and subtitle
in gt::tab_header()
are retained, but through an un-numbered \caption*{}
in the LaTeX code:
gt::gt(data = dt) |>
gt::tab_header(
title = gt::md("tab_header title"),
subtitle = gt::md("tab_header subtitle")
) |>
gt::as_latex() |>
as.character()
#> [1] "\\begin{longtable}{rr}\n\\caption*{\n{\\large tab\\_header title} \\\\ \n{\\small tab\\_header subtitle}\n} \\\\ \n\\toprule\nmpg & cyl \\\\ \n\\midrule\\addlinespace[2.5pt]\n21 & 6 \\\\ \n21 & 6 \\\\ \n\\bottomrule\n\\end{longtable}\n"
I understand that this a possible duplicate of #818. But, I am opening this one seeing that #818 is almost 3 years old.
sessionInfo()
#> R version 4.3.3 (2024-02-29 ucrt)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 19045)
#>
#> Matrix products: default
#>
#>
#> locale:
#> [1] LC_COLLATE=English_United States.utf8
#> [2] LC_CTYPE=English_United States.utf8
#> [3] LC_MONETARY=English_United States.utf8
#> [4] LC_NUMERIC=C
#> [5] LC_TIME=English_United States.utf8
#>
#> time zone:
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.6.5 cli_3.6.2 gt_0.10.1 knitr_1.45
#> [5] rlang_1.1.3 xfun_0.42 purrr_1.0.2 styler_1.10.2
#> [9] generics_0.1.3 glue_1.7.0 markdown_1.12 htmltools_0.5.7
#> [13] fansi_1.0.6 rmarkdown_2.26 R.cache_0.16.0 tibble_3.2.1
#> [17] evaluate_0.23 fastmap_1.1.1 yaml_2.3.8 lifecycle_1.0.4
#> [21] compiler_4.3.3 dplyr_1.1.4 fs_1.6.3 pkgconfig_2.0.3
#> [25] rstudioapi_0.15.0 R.oo_1.26.0 R.utils_2.12.3 digest_0.6.34
#> [29] R6_2.5.1 tidyselect_1.2.0 utf8_1.2.4 reprex_2.1.0
#> [33] pillar_1.9.0 commonmark_1.9.1 magrittr_2.0.3 R.methodsS3_1.8.2
#> [37] tools_4.3.3 withr_3.0.0 xml2_1.3.6
Created on 2024-03-20 with reprex v2.1.0
I managed to fix this in AaronGullickson#1 using tab_header()
and making it work in both longtable and floating table environments with the option to set a label for cross-referencing which, I think, is missing for GT tables in R Markdown. Context: #1588
Here are the four essential outputs:
Longtable with caption:
head(state.x77) |>
as.data.frame() |>
gt() |>
tab_options(latex.use.longtable = TRUE,
latex.tbl.pos = "!t") |>
tab_header(title = "This is a title",
subtitle = "subtitle",
label = "1") |>
gtsave("table-long-cap.tex")
\begingroup
\fontsize{12.0pt}{14.4pt}\selectfont
\begin{longtable}{rrrrrrrr}
\caption{
{\large This is a title} \\
{\small subtitle}
}\label{tab1} \\
\toprule
Population & Income & Illiteracy & Life Exp & Murder & HS Grad & Frost & Area \\
\midrule\addlinespace[2.5pt]
3615 & 3624 & 2.1 & 69.05 & 15.1 & 41.3 & 20 & 50708 \\
365 & 6315 & 1.5 & 69.31 & 11.3 & 66.7 & 152 & 566432 \\
2212 & 4530 & 1.8 & 70.55 & 7.8 & 58.1 & 15 & 113417 \\
2110 & 3378 & 1.9 & 70.66 & 10.1 & 39.9 & 65 & 51945 \\
21198 & 5114 & 1.1 & 71.71 & 10.3 & 62.6 & 20 & 156361 \\
2541 & 4884 & 0.7 & 72.06 & 6.8 & 63.9 & 166 & 103766 \\
\bottomrule
\end{longtable}
\endgroup
Longtable without caption:
head(state.x77) |>
as.data.frame() |>
gt() |>
tab_options(latex.use.longtable = TRUE,
latex.tbl.pos = "!t") |>
tab_header(title = "This is a title",
subtitle = "subtitle") |>
gtsave("table-long-nocap.tex")
\begingroup
\fontsize{12.0pt}{14.4pt}\selectfont
\begin{longtable}{rrrrrrrr}
\caption*{
{\large This is a title} \\
{\small subtitle}
} \\
\toprule
Population & Income & Illiteracy & Life Exp & Murder & HS Grad & Frost & Area \\
\midrule\addlinespace[2.5pt]
3615 & 3624 & 2.1 & 69.05 & 15.1 & 41.3 & 20 & 50708 \\
365 & 6315 & 1.5 & 69.31 & 11.3 & 66.7 & 152 & 566432 \\
2212 & 4530 & 1.8 & 70.55 & 7.8 & 58.1 & 15 & 113417 \\
2110 & 3378 & 1.9 & 70.66 & 10.1 & 39.9 & 65 & 51945 \\
21198 & 5114 & 1.1 & 71.71 & 10.3 & 62.6 & 20 & 156361 \\
2541 & 4884 & 0.7 & 72.06 & 6.8 & 63.9 & 166 & 103766 \\
\bottomrule
\end{longtable}
\endgroup
Floating table with caption:
head(state.x77) |>
as.data.frame() |>
gt() |>
tab_options(latex.use.longtable = FALSE,
latex.tbl.pos = "!t") |>
tab_header(title = "This is a title",
subtitle = "subtitle",
label = "table2") |>
gtsave("table-float-cap.tex")
\begin{table}[!t]
\caption{
{\large This is a title} \\
{\small subtitle}
}\label{tabtable2}
\fontsize{12.0pt}{14.4pt}\selectfont
\begin{tabular*}{\linewidth}{@{\extracolsep{\fill}}rrrrrrrr}
\toprule
Population & Income & Illiteracy & Life Exp & Murder & HS Grad & Frost & Area \\
\midrule\addlinespace[2.5pt]
3615 & 3624 & 2.1 & 69.05 & 15.1 & 41.3 & 20 & 50708 \\
365 & 6315 & 1.5 & 69.31 & 11.3 & 66.7 & 152 & 566432 \\
2212 & 4530 & 1.8 & 70.55 & 7.8 & 58.1 & 15 & 113417 \\
2110 & 3378 & 1.9 & 70.66 & 10.1 & 39.9 & 65 & 51945 \\
21198 & 5114 & 1.1 & 71.71 & 10.3 & 62.6 & 20 & 156361 \\
2541 & 4884 & 0.7 & 72.06 & 6.8 & 63.9 & 166 & 103766 \\
\bottomrule
\end{tabular*}
\end{table}
Floating table without caption:
head(state.x77) |>
as.data.frame() |>
gt() |>
tab_options(latex.use.longtable = FALSE,
latex.tbl.pos = "!t") |>
tab_header(title = "This is a title",
subtitle = "subtitle") |>
gtsave("table-float-nocap.tex")
\begin{table}[!t]
\caption*{
{\large This is a title} \\
{\small subtitle}
}
\fontsize{12.0pt}{14.4pt}\selectfont
\begin{tabular*}{\linewidth}{@{\extracolsep{\fill}}rrrrrrrr}
\toprule
Population & Income & Illiteracy & Life Exp & Murder & HS Grad & Frost & Area \\
\midrule\addlinespace[2.5pt]
3615 & 3624 & 2.1 & 69.05 & 15.1 & 41.3 & 20 & 50708 \\
365 & 6315 & 1.5 & 69.31 & 11.3 & 66.7 & 152 & 566432 \\
2212 & 4530 & 1.8 & 70.55 & 7.8 & 58.1 & 15 & 113417 \\
2110 & 3378 & 1.9 & 70.66 & 10.1 & 39.9 & 65 & 51945 \\
21198 & 5114 & 1.1 & 71.71 & 10.3 & 62.6 & 20 & 156361 \\
2541 & 4884 & 0.7 & 72.06 & 6.8 & 63.9 & 166 & 103766 \\
\bottomrule
\end{tabular*}
\end{table}
That looks great. Is it merged? Or, will it be merged?
It's not merged. I have made a pull request to @AaronGullickson at https://github.com/AaronGullickson/gt/pull/1 who was initially working on the LaTex floating table.
I have also left the above solution for another (https://github.com/AaronGullickson/gt/pull/2), where tab_caption()
is used for cross-referencing. This was done so the Latex output was in line with the html output. I also updated the knitr helper functions so that cross-referencing is possible using the chunk options in Bookdown. You can download it from here: pak::pak(nielsbock/gt@floating-table)
if you would like to check it out!
I will try to get to it today or tomorrow
I came here to report a similar issue/bug regarding the table captions when rendering to quarto pdf
---
title: "mtcars quarto table captions"
format:
pdf:
toc: true
lot: true
lof: true
keep-tex: true
keep-md: true
---
```{r}
#| label: tbl-mtcars
mtcars |>
head() |>
gt::gt() |>
gt::tab_caption(caption = deparse(substitute(mtcars)))
```
```{r}
#| label: tbl-mtcars-tail
#| tbl-cap: "mtcars tail"
mtcars |>
tail() |>
gt::gt()
```
```{r}
#| lst-label: lst-mtcars-options
#| lst-cap: "mtcars table options"
TBL <- mtcars |>
head() |>
gt::gt() |>
gt::tab_caption(caption = deparse(substitute(mtcars)))
TBL$`_options` |>
dplyr::filter(parameter == 'table_caption')
TBL$`_options` |>
dplyr::filter(parameter == 'table_caption') |>
dplyr::pull(value)
```
the development version of gt now includes a fix for this, thanks to @nielsbock, in case people want to try it out!
pak::pak("rstudio/gt")
We'd love to receive your feedback so please open a new issue if something is not working as expected.