kableExtra inserts unwanted extra line into some cells, depending on cell value

421 Views Asked by At

I am using kableExtra to generate an Rmarkdown table (in Rstudio 1.2.1335, Windows 10). One of the cells ends up with it's value pushed to another line which messes up the line spacing (see image below). The odd part is that if I manually replace that cell value in the matrix with another value, it sometimes fixes it, depending on the replacement value. My code is below (I have tried and failed to make a reproducible example - the problem only seems to crop up with my actual data).

est1 <- as.matrix(cbind(round(apply(sexClass2,2,mean),0),
             round(apply(sexClass2,2,mlv,method="lientz",bw=0.5),0),
             round(t(apply(sexClass2,2,hdi)),0)))
#est1[1,4] <- 38
load("FR_Coll_20200815_20201115_weekly_theta_df_Constrained.RData")
est2 <- cbind(round(apply(sexClass2,2,mean),0),
             round(apply(sexClass2,2,mlv,method="lientz",bw=0.5),0),
             round(t(apply(sexClass2,2,hdi)),0))
load("FR_Coll_20200815_20201115_weekly_theta.RData")
est3 <- cbind(round(apply(sexClass2,2,mean),0),
             round(apply(sexClass2,2,mlv,method="lientz",bw=0.5),0),
             round(t(apply(sexClass2,2,hdi)),0))
est <- rbind(est1,est2,est3)

cap <- "Abundance estimates for elk from the FR camera grid. Estimates reflect the subtraction of any animals known to have died during the study period."

colnames(est) <- c("Mean","Mode","LCrL","UCrL")
rownames(est) <- rep(c("Cows","Bulls","Calves","Cows + Calves", "Total"),times=3)
estFR <- est %>%
  kable(booktabs = TRUE, caption=cap, linesep = "",align=rep('r',4),escape=FALSE) %>%
  kable_styling(latex_options = c("hold_position"),full_width = FALSE) %>% 
  column_spec(1, width = "6cm")%>%
  column_spec(2:5, width = "2cm") %>%
  pack_rows("Group-specific detection parameters", 1,5) %>%
  pack_rows("Group-specific detection parameters, and IDs constrained", 6,10)%>%
  pack_rows("Constant detection parameters", 11,15)  

This produces the following table:

enter image description here

If I un-comment that line est1[1,4] <- 38, then the problem goes away. If I replace the value with 1 or 29 or 41, etc., the problem also goes away. But if I replace the value with say, 39 or 40, then the cell has that unwanted extra line.

Lastly, if I generate that matrix est1 using the exact same values, then there is no problem. But I also load in and calculate the values in est2 and est3, and there is no problem there.

I have three identically constructed table (exact same code, changing only the input data files). In one I see the behavior described above, for just that one cell. In another, I see the behavior for all the right-column cells in that first group (but not in the last two groups), and in the third, there is no problem at all.

I've tried various other tricks, like est1 <- est1*1, to no avail. Oddly, est1 <- est1/2 makes the spacing problem go away, even though the cell value has more characters (which should make it more likely to wrap). And est1/2*2 did not work.

Can anyone provide an explanation or solution to this seemingly very strange behavior?

2

There are 2 best solutions below

0
On BEST ANSWER

I have identified the issue (thanks to the issues posted here, here, and here). The problem is that when two rows in the table are identical, a \vphantom{1} is inserted into the LaTex code for the first identical row, to differentiate the two identical rows. I noticed this when I examined the Latex file - the first row of the table was

\hspace{1em}Cows & 29 & 28 & 19 & \vphantom{1} 39\\

A work-around (but maybe not a very satisfactory and general solution) was to move that inserted code to the end of the line, like est[1,4] <- "39\\vphantom{1}", which produced

\hspace{1em}Cows & 29 & 28 & 19 & 39\vphantom{1}\\

in the Latex code, which then correctly formatted the pdf output.

I am not sure why the identical rows are problematic (why it is necessary to make them non-identical), and also don't know if there is a better general solution that does not require changing a value in the table specification.

0
On

A somewhat more general, yet still hacky solution is replacing \vphantom{1} in the knitr_kable object.

First, reproduce the issue:

> library(tidyverse)
> library(kableExtra)
> tbl = tibble(a = c(1,1), b = c(2,2)) %>% 
+   kbl(format = "latex") %>% 
+   column_spec(1)
> tbl

\begin{tabular}[t]{>{}r|r}
\hline
a & b\\
\hline
1 & \vphantom{1} 2\\
\hline
1 & 2\\
\hline
\end{tabular}

Delete all occurrences of \vphantom{1}:

> tbl[1] = tbl %>% 
+   str_remove_all(fixed(" \\vphantom{1}"))
> tbl

\begin{tabular}[t]{>{}r|r}
\hline
a & b\\
\hline
1 & 2\\
\hline
1 & 2\\
\hline
\end{tabular}

Word of caution: This has worked well for me in a few instances and I did not find any reason why identical rows are made non-identical. However, it seems likely that there is a reason for this behavior and blindly removing the \vphantom{1} might break things.