kableExtra
kableExtra copied to clipboard
threeparttable overrides centering with caption
Describe the bug
Using add_footnote(..., threeparttable = TRUE) overrides kable_styling(position = "center") if a caption is also provided. First reported here but identified as an upstream bug.
To Reproduce
Here's a screenshot of a PDF demonstrating the bug.

To break down what's happening above, let's cat the raw LaTeX code for each example. First, quickly load the package and create the table.
library(kableExtra)
dat = mtcars[1,1:4]
In the base case with threeparttable turned off, the \centering option comes immediately before the begin{tabular} environment. So this works as expected.
kbl(dat, caption = "A nice table", format = "latex") %>%
add_footnote("A short note.", threeparttable = FALSE) %>% ## NO 3PT
kable_styling(position = "center") %>%
cat()
#> \begin{table}
#>
#> \caption{A nice table}
#> \centering
#> \begin{tabular}[t]{l|r|r|r|r}
#> \hline
#> & mpg & cyl & disp & hp\\
#> \hline
#> Mazda RX4 & 21 & 6 & 160 & 110\\
#> \hline
#> \multicolumn{5}{l}{\textsuperscript{a} A short note.}\\
#> \end{tabular}
#> \end{table}
In contrast, switching threeparttable on leads to a new begin{threeparttable} environment, which precedes the \centering option. So the latter is overridden, leading to the unexpected left-alignment of the table.
kbl(dat, caption = "A nice table", format = "latex") %>%
add_footnote("A short note.", threeparttable = TRUE) %>% # CHANGED
kable_styling(position = "center") %>%
cat()
#> \begin{table}
#>
#> \begin{threeparttable}
#> \caption{\label{tab:unnamed-chunk-2}A nice table}
#> \centering
#> \begin{tabular}[t]{l|r|r|r|r}
#> \hline
#> & mpg & cyl & disp & hp\\
#> \hline
#> Mazda RX4 & 21 & 6 & 160 & 110\\
#> \hline
#> \end{tabular}
#> \begin{tablenotes}
#> \small
#> \item [a] A short note.
#> \end{tablenotes}
#> \end{threeparttable}
#> \end{table}
Finally, to emphasize the interplay between these elements, note that turning off caption leads back to the correct behaviour, where \centering precedes the begin{threeparttable} environment.
kbl(dat, caption = NULL, format = "latex") %>% ## Now caption = NULL
add_footnote("A short note.", threeparttable = TRUE) %>%
kable_styling(position = "center") %>%
cat()
#> \begin{table}
#> \centering
#> \begin{threeparttable}
#> \begin{tabular}[t]{l|r|r|r|r}
#> \hline
#> & mpg & cyl & disp & hp\\
#> \hline
#> Mazda RX4 & 21 & 6 & 160 & 110\\
#> \hline
#> \end{tabular}
#> \begin{tablenotes}
#> \small
#> \item [a] A short note.
#> \end{tablenotes}
#> \end{threeparttable}
#> \end{table}
Solution
Calling kable_styling(position = "center") should always lead inject \centering directly below \begin{table}, rather than after an intermediate environment like \begin{threeparttable}. I imagine this is true for other arguments that apply to kable_styling, so should hopefully be a relatively simple fix.