sweave, xtable, longtable and alternating row colo

2019-05-16 10:43发布

This existing question covers a way to alternate row colors in a latex table by post-processing the output from print.xtable(), but I think it's possible to achieve the same thing by using the add.to.row argument of print.xtable() as described on stats.stackexchange, avoiding the need for post-processing, which is nice with Sweave. That answer deals with coloring the background of one specific row, but I think it can be extended to coloring all the odd rows.

The problem I'm running into has to do with the add.to.row argument, making the length of list pos equal the length of character vector command. The help file for print.xtable() describes:

add.to.row: a list of two components. The first component (which should be called 'pos') is a list contains the position of rows on which extra commands should be added at the end, The second component (which should be called 'command') is a character vector of the same length of the first component which contains the command that should be added at the end of the specified rows. Default value is 'NULL', i.e. do not add commands.

when using the longtable environment, you can use this add.to.row argument to define the "header" rows of your table that should be printed on every page, like so:

library(xtable)
my.df=data.frame(a=c(1:10),b=letters[1:10])
print(xtable(my.data.frame,caption="My Table"),
      tabular.environment="longtable",
      floating=FALSE,
      hline.after=c(-1,nrow(my.data.frame)),
      add.to.row=list(pos=list(0),command="\\hline \\endhead ")

I need to keep this functionality, and add the additional functionality that every other row should get the command \\rowcolor[gray]{0.8}

Sounds simple enough. pos should be something like list=(0,1,3,5,7,9) and command should be something like c("\\hline \\endhead ","\\rowcolor[gray]{0.8}","\\rowcolor[gray]{0.8}","\\rowcolor[gray]{0.8}","\\rowcolor[gray]{0.8}","\\rowcolor[gray]{0.8}")

Of course, I want to take advantage of some built in functions to build the odd-row sequence and the repetition of "\\rowcolor[gray]{0.8}", so I thought of:

pos=list(0,seq(from=1,to=nrow(my.df),by=2))

and

command=c("\\hline \\endhead ",
          rep("\\rowcolor[gray]{0.8}",length(seq(from=1,to=nrow(my.df),by=2))))

my problem is that the pos list above evaluates to:

> pos
[[1]]
[1] 0

[[2]]
[1] 1 3 5 7 9

which has length 2...it needs to have length 6 in this case.

1条回答
倾城 Initia
2楼-- · 2019-05-16 11:21

The trick is to flatten out the list. There may be a prettier way, the following does the trick.

pos=list(as.list(c(0,seq(from=1,to=nrow(my.df),by=2))))[[1]]

The whole package is then:

library(xtable)
my.df=data.frame(a=c(1:10),b=letters[1:10])

print(xtable(my.df,caption="My Table"),
      tabular.environment="longtable",
      floating=FALSE,
      hline.after=c(-1,nrow(my.df)),
      add.to.row=list(
      pos=list(as.list(c(0,seq(from=1,to=nrow(my.df),by=2))))[[1]],
      command=c("\\hline \\endhead ",
      rep("\\rowcolor[gray]{0.8}",length(seq(from=1,to=nrow(my.df),by=2)))))
      )

which produces

% latex table generated in R 2.14.2 by xtable 1.7-0 package
% Thu Jan 31 12:52:55 2013
\begin{longtable}{rrl}
  \hline
 & a & b \\ 
  \hline \endhead 1 &   1 & a \\ 
   \rowcolor[gray]{0.8}2 &   2 & b \\ 
  3 &   3 & c \\ 
   \rowcolor[gray]{0.8}4 &   4 & d \\ 
  5 &   5 & e \\ 
   \rowcolor[gray]{0.8}6 &   6 & f \\ 
  7 &   7 & g \\ 
   \rowcolor[gray]{0.8}8 &   8 & h \\ 
  9 &   9 & i \\ 
   \rowcolor[gray]{0.8}10 &  10 & j \\ 
   \hline
\hline
\caption{My Table}
\end{longtable}

the formatting of the latex is a little ugly, and since \rowcolor is supposed to come before the row, even though we specified 1,3,5,9 we get coloring on 2,4,6,8 of the output.

查看更多
登录 后发表回答