3

I am using R packages (xtable and knitr) and Latex packages (longtable and hyperref) to prepare a document.

One of my tables is very long and splits onto multiple pages. It turned out that the "List of Table" shows every page number at which this table appears, but all hyperlinks bring me to the beginning of this table.

My question is, in "List of Table" how can I just show the first page number at which this table appears.

\documentclass{article}
\usepackage{longtable}
\usepackage{hyperref}

<<setup, include=FALSE, cache=FALSE>>=
library(knitr)
library(xtable)
@

\begin{document}
\listoftables
\newpage

<<echo=FALSE,results='asis'>>=
## some customerized settings for "longtable"
addtorow          <- list()
addtorow$pos      <- list()
addtorow$pos[[1]] <- c(0)
addtorow$command  <- c(paste("\\hline \n",
                             "\\endhead \n",
                             "\\hline \n",
                             "{\\footnotesize Continued on next page} \n",
                             "\\endfoot \n",
                             "\\endlastfoot \n",sep=""))
## create a long table
d <- data.frame(ID=rep(1:300), LAB=rnorm(300))

## execute "xtable"
dTab <- xtable(d, caption="This is Table 1")

print(dTab,    
      tabular.environment = "longtable",
      floating = FALSE,
      include.colnames = TRUE,
      include.rownames = FALSE, #addtorow substitute default row names
      add.to.row = addtorow,    # make the substitution here
      hline.after=c(-1),        # addtorow substitute default hline for first row
      caption.placement="top"
)
@

\end{document}
CL.
  • 14,577
  • 5
  • 46
  • 73
Yaming
  • 97
  • 6

1 Answers1

4

This question needs to be answered in two parts:

  1. Which LaTeX code is required to include only the first part of the table in the LOF (List of Figures)?
  2. How to make xtable generate that code?

The first part already has an answer on tex.stackexchange: How to use a longtable with only one entry in the list of tables. It boils down to use \caption{…} in the first header of the table and \caption*{…} in the following headers.

Including the footer from the question, the required LaTeX looks like this:

\begin{longtable}{rr}
    \caption{This is Table 1} \\ \hline
  \endfirsthead
    \caption*{This is Table 1} \\ \hline
    ID & LAB \\
    \hline
  \endhead
    \hline
    {\footnotesize Continued on next page}
  \endfoot
  \endlastfoot
ID & LAB \\ 
\hline
1 & 1.08 \\ 
2 & -0.99 \\ 
3 & 1.64 \\ 

(Note that the ID & LAB after \endlastfoot could also go into the first header part, but the structure above is easier to generate using xtable.)


The second part is a little bit more tricky. By default, xtable includes a \caption command in the table header. Using the add.to.row option of print.xtable, we can add content in front of the table body, but we cannot add content before the \caption command (as far as I know).

Therefore, in order to achieve the structure shown above, we suppress as much auto-generated LaTeX code as possible and add the correct table header manually.

This can by done with the option only.contents of print.xtable. All arguments concerning metadata of the table (latex.environment, floating and so on) become obsolete because we write the table header on our own:

<<echo=FALSE, results='asis'>>=

  ## create a long table
  d <- data.frame(ID=rep(1:300), LAB=rnorm(300))

  ## execute "xtable"
  dTab <- xtable(d)

  cat(sprintf("
  \\begin{longtable}{rr}
    \\caption{%1$s} \\\\ \\hline
    \\endfirsthead
    \\caption*{%s} \\\\ \\hline
    %2$s \\\\
    \\hline
    \\endhead
    \\hline
    {\\footnotesize %3$s}
    \\endfoot
    \\endlastfoot",
  "This is Table 1",
  paste(colnames(dTab), collapse = " & "),
  "Continued on next page"))

  print(dTab,
        include.colnames = TRUE,
        include.rownames = FALSE,
        only.contents = TRUE
  )

  cat("\\end{longtable}")
@

As requested, the LOF contains only one entry:

Output


Full code:

\documentclass{article}
\usepackage{longtable}
\usepackage{hyperref}

<<setup, include=FALSE, cache=FALSE>>=
  library(knitr)
  library(xtable)
@

\begin{document}
\listoftables

<<echo=FALSE, results='asis'>>=

  ## create a long table
  d <- data.frame(ID=rep(1:300), LAB=rnorm(300))

  ## execute "xtable"
  dTab <- xtable(d)

  cat(sprintf("
  \\begin{longtable}{rr}
    \\caption{%1$s} \\\\ \\hline
    \\endfirsthead
    \\caption*{%s} \\\\ \\hline
    %2$s \\\\
    \\hline
    \\endhead
    \\hline
    {\\footnotesize %3$s}
    \\endfoot
    \\endlastfoot",
  "This is Table 1",
  paste(colnames(dTab), collapse = " & "),
  "Continued on next page"))

  print(dTab,
        include.colnames = TRUE,
        include.rownames = FALSE,
        only.contents = TRUE
  )

  cat("\\end{longtable}")
@

\end{document}

Addendum

To address the additional question of how to rotate the column names:

  • Add \usepackage{rotating} to the preamble.
  • Use paste(paste("\\begin{sideways}", colnames(dTab), "\\end{sideways}"), collapse = " & ") instead of paste(colnames(dTab), collapse = " & ").
  • Add rotate.colnames = TRUE to the print.xtable call.
Community
  • 1
  • 1
CL.
  • 14,577
  • 5
  • 46
  • 73
  • You gave me a very thorough explanation for under the hood mechanism! I might violate the forum rule here, but I've been bothered by the similar difficulty for a figure that expands to multiple pages. See a question I posted in this [link](http://tex.stackexchange.com/questions/191487/sub-figures-in-multiple-pages-but-with-one-figure-caption-and-showing-continued). Would you be able to shed some light on it too? My skill in `Latex` is premature. – Yaming Oct 16 '15 at 14:12
  • I came back to this question half year later. Suppose I want to rotate the column names in the table, then adding `rotate.colnames=TRUE` as an extra control in 'print(dTab)` won't work. How can I achieve this? – Yaming May 02 '16 at 21:44
  • @Yaming I added a short section at the very bottom of the answer. – CL. May 03 '16 at 09:10
  • Thanks for your advice and contribution to the community! – Yaming May 04 '16 at 00:38
  • I want to expand this question again. Suppose I include `names(dTab)[names(dTab)=="LAB"] <- "$LAB_{dummy}~(IU/L)$"` after line of `dTab <- xtable(d)`, by doing this way, I expect subscript of word of dummy in the column names. However it turned out that the first page of table just shows `$LAB_{dummy}~(IU/L)$` verbatim (the following pages of table show this column name formatted as requested). I wish there is a more straightforward way to solve this problem. – Yaming May 04 '16 at 13:04
  • You need to add `sanitize.colnames.function = identity` to `print.xtable`. Why all this is "not straightforward": Well, `xtable` provides a lot of functionality, but here we're doing something "out of the box". That's why we need to do some manual coding … But actually, your latest problem (math in column names) is due to standard `xtable` behavior, see the section on `sanitize.rownames.function` in `?print.xtable`. – CL. May 04 '16 at 13:16
  • You have a good answer. For most people who don't deeply know the under-the-hood mechanism, like me. I struggled. Another trouble I have if I follow this manual manipulation. I put `names(dTab)[2] <- paste(names(dTab)[2], "a")` after `dTab <- xtable(d)`, I then add `sanitize.colnames.function=function(str)(gsub(c("a"), c("\\footnote{This is ALT}"), str,fixed=TRUE) ` as another control in `print`. It turned out that the first page show "LAB 1"correctly in header, and a corresponding footer, but the following pages only show "Lab a" as header – Yaming May 04 '16 at 14:49