Line breaks in xtable cells

3.2k views Asked by At

I'm using xtable to automatically generate LaTeX tables and would like to force a line-feed/break within cells.

This can be done using \newline within a cell, however I'm having trouble preventing xtable from substituting my backslashes (\) with $\backslash$.

Heres an example....

library(magrittr)
library(xtable)
my.data <- cbind(c("1", "2", "3"),
                 c("0", "1", "2"),
                 c("2", "3", "4")) %>%
           as.data.frame()
## Generate output variable
my.data$out <- paste0(my.data$V1,
                      " \\newline (",
                      my.data$V2,
                      " to ",
                      my.data$V3,
                      ")")
## Check the data frame...
my.data
  V1 V2 V3                  out
1  1  2  3 1 \\newline (2 to 3)
2  0  1  2 0 \\newline (1 to 2)
3  2  3  4 2 \\newline (3 to 4)
## Now generate xtable
xtable(my.data)
% latex table generated in R 3.2.0 by xtable 1.7-4 package
% Wed Jun 24 11:51:59 2015
\begin{table}[ht]
\centering
\begin{tabular}{rllll}
  \hline
  & V1 & V2 & V3 & out \\ 
  \hline
1 & 1 & 2 & 3 & 1 $\backslash$newline (2 to 3) \\ 
2 & 0 & 1 & 2 & 0 $\backslash$newline (1 to 2) \\ 
3 & 2 & 3 & 4 & 2 $\backslash$newline (3 to 4) \\ 
  \hline
\end{tabular}
\end{table}

The paste0() works fine as expected, but passing this data frame to xtable does not result in what I expected(/hoped for) which is....

xtable(my.data)
% latex table generated in R 3.2.0 by xtable 1.7-4 package
% Wed Jun 24 11:51:59 2015
\begin{table}[ht]
\centering
\begin{tabular}{rllll}
  \hline
  & V1 & V2 & V3 & out \\ 
  \hline
1 & 1 & 2 & 3 & 1 \newline (2 to 3) \\ 
2 & 0 & 1 & 2 & 0 \newline (1 to 2) \\ 
3 & 2 & 3 & 4 & 2 \newline (3 to 4) \\ 
  \hline
\end{tabular}
\end{table}

So that when parsed through LaTeX I get line breaks in that cell.

A similar question about line breaks in captions suggests using double-escaped backslashes but that doesn't work in this instance either...

my.data$out <- paste0(my.data$V1,
                      " \\\\newline (",
                      my.data$V2,
                      " to ",
                      my.data$V3,
                      ")")
% latex table generated in R 3.2.0 by xtable 1.7-4 package
% Wed Jun 24 11:57:04 2015
\begin{table}[ht]
\centering
\begin{tabular}{rllll}
  \hline
 & V1 & V2 & V3 & out \\ 
  \hline
1 & 1 & 2 & 3 & 1 $\backslash$$\backslash$newline (2 to 3) \\ 
  2 & 0 & 1 & 2 & 0 $\backslash$$\backslash$newline (1 to 2) \\ 
  3 & 2 & 3 & 4 & 2 $\backslash$$\backslash$newline (3 to 4) \\ 
   \hline
\end{tabular}
\end{table}

Next I looked at the xtable help and graph gallery and thought I might be able to use the sanitise.text.function to specify explicitly to substitute \ with \ (and I could then just use \newline within my paste0() call) but unfortunately this doesn't work either as the second \ is treated as escaping the following closing double quote...

xtable(my.data, sanitise.text.function = function(str)gsub("\", "\",str,fixed=TRUE))
Error: unexpected input in:
"xtable(my.data,
       sanitise.text.function = function(str)gsub("\", "\"

Could I use the whole string \newline and substitute it with itself?

my.data$out <- paste0(my.data$V1,
                      " \newline (",
                      my.data$V2,
                      " to ",
                      my.data$V3,
                      ")")
xtable(my.data, sanitise.text.function = function(str)gsub("\newline", "\newline",str,fixed=TRUE))
% latex table generated in R 3.2.0 by xtable 1.7-4 package
% Wed Jun 24 12:05:25 2015
\begin{table}[ht]
\centering
\begin{tabular}{rllll}
  \hline
 & V1 & V2 & V3 & out \\ 
  \hline
1 & 1 & 0 & 2 & 1 
ewline (0 to 2) \\ 
2 & 2 & 1 & 3 & 2 
ewline (1 to 3) \\ 
3 & 3 & 2 & 4 & 3 
ewline (2 to 4) \\ 
   \hline
\end{tabular}
\end{table}

No joy since the \n is now treated as a linebreak when parsed through xtable.

This thread suggested using identity as the function argument to sanitise.text.function but that didn't work either (nor does using an identity function of function(x){x}). I found a post on R-help asking similar (but the problem was with \t being interpreted as a tab) but that didn't work either (again output omitted for brevity).

 my.data
  V1 V2 V3                  out
1  1  0  2 1 \\newline (0 to 2)
2  2  1  3 2 \\newline (1 to 3)
3  3  2  4 3 \\newline (2 to 4)
xtable(my.data, sanitise.text.function = identity)
% latex table generated in R 3.2.0 by xtable 1.7-4 package
% Wed Jun 24 13:09:47 2015
\begin{table}[ht]
\centering
\begin{tabular}{rllll}
  \hline
 & V1 & V2 & V3 & out \\ 
  \hline
1 & 1 & 0 & 2 & 1 $\backslash$newline (0 to 2) \\ 
2 & 2 & 1 & 3 & 2 $\backslash$newline (1 to 3) \\ 
3 & 3 & 2 & 4 & 3 $\backslash$newline (2 to 4) \\ 
 \hline
\end{tabular}
\end{table}

my.data
  V1 V2 V3                 out
1  1  0  2 1 \newline (0 to 2)
2  2  1  3 2 \newline (1 to 3)
3  3  2  4 3 \newline (2 to 4)
xtable(my.data,
       sanitise.text.function = identity)
% latex table generated in R 3.2.0 by xtable 1.7-4 package
% Wed Jun 24 13:28:28 2015
\begin{table}[ht]
\centering
\begin{tabular}{rllll}
  \hline
 & V1 & V2 & V3 & out \\ 
  \hline
1 & 1 & 0 & 2 & 1 
ewline (0 to 2) \\ 
  2 & 2 & 1 & 3 & 2 
ewline (1 to 3) \\ 
  3 & 3 & 2 & 4 & 3 
ewline (2 to 4) \\ 
   \hline
\end{tabular}
\end{table}

It feels like I'm close with using sanitise.text.function option but I can't work it out. Is there a way of doing this somehow?

Thanks in advance for any suggestions/insights.

2

There are 2 answers

1
Paul On BEST ANSWER

Did you configure sanitize.*.function using options() rather than print()? For example,

options(xtable.sanitize.text.function=identity)

prevents conversion of \ with $\backslash$ in cells.

0
nsi2534 On

I can confirm that xtable.sanitize.text.function works. I used it as below

options(xtable.sanitize.text.function = line_break_function)

line_break_function <- function(x){
gsub("$<$br$>$","<br>",x)
}

I used it as below to add line breaks to text blocks in a summarise function

cv %>%
group_by() %>%
summarise(colname = paste(`summary`,":",`Submit Date`,collapse = ",<br>"))

print(xtable, type = "html")