How to only show table caption once in “list of ta

2019-04-16 23:01发布

问题:

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}

回答1:

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:


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.