Skip to content

latex tables for 3+ dimensional tables/arrays

7 messages · David Winsemius, Michael Friendly, Richard M. Heiberger +1 more

#
I'm looking for an R method to produce latex versions of tables for 
table/array objects of 3 or more dimensions,
which, of necessity is flattened to a 2D display, for example with 
ftable(), or vcd::structable, as shown below.
I'd be happy to settle for a flexible solution for the 3D case.

 > UCB <- aperm(UCBAdmissions, c(2, 1, 3))
 > ftable(UCB)
                 Dept   A   B   C   D   E   F
Gender Admit
Male   Admitted      512 353 120 138  53  22
        Rejected      313 207 205 279 138 351
Female Admitted       89  17 202 131  94  24
        Rejected       19   8 391 244 299 317
 > structable(Dept ~ Admit+Gender, UCBAdmissions)
                 Dept   A   B   C   D   E   F
Admit    Gender
Admitted Male        512 353 120 138  53  22
          Female       89  17 202 131  94  24
Rejected Male        313 207 205 279 138 351
          Female       19   8 391 244 299 317


I tried using the xtable package but discovered that xtable.table is 
silently
wrong for tables of length(dim(x))>2.  E.g., for a 2 x 2 x 6 table, we 
get only UCBAdmissions[,,1]

 > xtable(UCBAdmissions)
% latex table generated in R 2.11.1 by xtable 1.5-6 package
% Tue Nov 16 13:23:44 2010
\begin{table}[ht]
\begin{center}
\begin{tabular}{rrr}
   \hline
& Male & Female \\
   \hline
Admitted & 512.00 & 89.00 \\
   Rejected & 313.00 & 19.00 \\
    \hline
\end{tabular}
\end{center}
\end{table}
 >

The author of xtable tells me that only 2-way tables are presently 
implemented, and, while I would normally
look to Hmisc for all things LaTeX, I don't find anything useful there:

 > library(Hmisc)
 > methods("latex")
  [1] latex.bystats                  latex.bystats2
  [3] latex.default                  latex.describe
  [5] latex.describe.single          latex.function
  [7] latex.list                     latex.responseSummary
  [9] latex.summary.formula.cross    latex.summary.formula.response
[11] latex.summary.formula.reverse
 > latex(UCB)
Error in x[, j] : incorrect number of dimensions
 > traceback()
3: format.df(object, dcolumn = dcolumn, na.blank = na.blank, 
numeric.dollar = numeric.dollar,
        cdot = cdot, math.row.names = math.row.names, math.col.names = 
math.col.names,
        double.slash = double.slash, ...)
2: latex.default(UCB)
1: latex(UCB)
#
On Dec 2, 2010, at 3:47 PM, Michael Friendly wrote:

            
?latex  # yes I know you are aware of this but it seemed as though you  
hadn't read its help page.
# Attached is the output on my device from the following command:
latexVerbatim( ftable(UCB))

# (OK, so I can't speell.)
#
On 12/2/2010 4:04 PM, David Winsemius wrote:
Perhaps I should have been more explicit.  I can always use verbatim as 
a fall-back, but what I want is
something to produce the *latex* code to give something actually 
formatted as a latex table.

Below is
something along the lines of what I want (similar to  t(  
structable(Dept ~ Admit+Gender, UCBAdmissions)) ).
This was written *directly* from an object in SAS/IML by routines I 
wrote some time ago.  I'm looking
for an R equivalent, something that can be used in Sweave documents.

% Table berk3 written by md2tex 12Dec99
\begin{table}[htb]
  \caption{Berkeley data: 3-way table}\label{tab:berk3}
  \begin{center}
  \begin{tabular}{|c|rr|rr|}
   \hline
& \multicolumn{2}{c}{Male} & \multicolumn{2}{c|}{Female} \\ \cline{2-5}
   Dept & Admit & Reject & Admit & Reject  \\
   \hline
   A & 512 & 313 & 89 & 19 \\
   B & 353 & 207 & 17 & 8 \\
   C & 120 & 205 & 202 & 391 \\
   D & 138 & 279 & 131 & 244 \\
   E & 53 & 138 & 94 & 299 \\
   F & 22 & 351 & 24 & 317 \\
   \hline
  \end{tabular}
  \end{center}
\end{table}
#
David Winsemius wrote:
Some time ago, I did a quick hack. Don't know if it helps, it was good
enough for my purpose.

## RNW file

\documentclass{article}
\usepackage{Sweave}
\usepackage{ctable}
\SweaveOpts{engine=R,eval=TRUE, eps=FALSE, pdf=TRUE, strip.white=FALSE,
echo=FALSE, results=hide, width=6,height=4, prefix.string=graphics/era}

\begin{document}
\section{Test FTable}

<<>>=
library(Hmisc)
df = data.frame(drug=sample(c("P","V","G","D"),100,TRUE),
                season=sample(c("Spr","Sum"),100,TRUE), 
                Hist1=sample(c("Pos","Neg","??"),100,TRUE),
                Hist2=sample(c("AZ","BZ"),100,TRUE))
ft <- ftable(drug~season+Hist1+Hist2,data=df)                
@

<<results= verbatim>>=
ft
@


<<results= tex>>=
latex.ftable = function(object,title="",caption,label,pos="!tbp",...){
  ft = format(object,quote=FALSE)
  nr = nrow(ft)
  nc = ncol(ft)
  cv = attr(object,"col.vars")
  rv = attr(object,"row.vars")
  ncolvars = length(cv)
  nrowvars = length(rv)
  
  ft[ncolvars,1:nrowvars] = ft[ncolvars+1,1:nrowvars]
 
  align1 = paste(rep("l",ncolvars),collapse="")
  align2 = paste(rep("r",nc-ncolvars),collapse="")
  cat("\\ctable[ caption={",caption,"}, label=",label,",pos=",pos,",
botcap]{",
    align1,align2,"}{} \n{\\FL\n", sep="")
  for (i in 1:ncolvars){
    head = paste("\\multicolumn{1}{c}{",ft[i,],"}",collapse="&\n",sep="")  
    if (i == ncolvars)
      cat(head, "\n\\ML\n") else
    cat(head, "\n\\NN\n")
      
  }
  for (i in (ncolvars+2):(nr)) { 
    cat(paste(ft[i,],collapse="&"))
    if (i != nr ) {
      if (substr(ft[i,1],1,1) ==' ' & substr(ft[i+1,1],1,1) !=' '){
        cat("\\ML\n")
      } else 
      cat("\\NN\n")
    }
  }
  cat("\n\\LL\n}\n")
}

latex(ft,caption,"This is an ftable",label="tab:ftable")
@

\end{document}
#
On 12/3/2010 4:19 AM, Dieter Menne wrote:
[snip]

Yes, thanks -- that's a good start.  Ideally, I'd like to have something 
that could also take a file= argument and write to a file
like other latex() methods, but that shouldn't be too hard.

-M
1 day later
#
Hi Rich,
I was looking for something that I could make general, as a latex.ftable
method for ftable objects.  I realize you showed how to do this for a
particular case, but I'm having a bit of trouble translating this into
a general solution for 1 or more row variables and 1 or more col variables.

This is most likely because latex() offers a bewildering collection
of arguments I don't fully understand how to apply in this case.

Here is my current sketch, with test cases below, one of which fails...

latex.ftable <- function(object, numeric.dollar=FALSE,  ...) {
   cv <- attr(object,"col.vars")
   rv <- attr(object,"row.vars")
   ncv <- length(cv)
   nrv <- length(rv)
   colheads <- cv[[1]]
   cgroup <- if (ncv>1) cv[[1]] else NULL
   rowname <- rv[[2]]
   rgroup <- if (nrv>1) rv[[1]] else NULL
   latex.default(object, colheads=colheads, rowname=rowname,
   	cgroup=cgroup, rgroup=rgroup, numeric.dollar=numeric.dollar, ...)
}

 > ft <- ftable(UCBAdmissions)
 > ft
                 Dept   A   B   C   D   E   F
Admit    Gender
Admitted Male        512 353 120 138  53  22
          Female       89  17 202 131  94  24
Rejected Male        313 207 205 279 138 351
          Female       19   8 391 244 299 317
 > str(ft)
  ftable [1:4, 1:6] 512 89 313 19 353 17 207 8 120 202 ...
  - attr(*, "row.vars")=List of 2
   ..$ Admit : chr [1:2] "Admitted" "Rejected"
   ..$ Gender: chr [1:2] "Male" "Female"
  - attr(*, "col.vars")=List of 1
   ..$ Dept: chr [1:6] "A" "B" "C" "D" ...
 >

 > latex(ft, file="")
% latex.default(object, colheads = colheads, rowname = rowname, 
cgroup = cgroup, rgroup = rgroup, numeric.dollar = numeric.dollar, 
...)
%
\begin{table}[!tbp]
  \begin{center}
  \begin{tabular}{lrrrrrr}\hline\hline
\multicolumn{1}{l}{object}&\multicolumn{1}{c}{A}&\multicolumn{1}{c}{B}&\multicolumn{1}{c}{C}&\multicolumn{1}{c}{D}&\multicolumn{1}{c}{E}&\multicolumn{1}{c}{F}\tabularnewline
\hline
{\bfseries Admitted}&&&&&&\tabularnewline
~~Male&512&353&120&138& 53& 22\tabularnewline
~~Female& 89& 17&202&131& 94& 24\tabularnewline
\hline
{\bfseries Rejected}&&&&&&\tabularnewline
~~Male&313&207&205&279&138&351\tabularnewline
~~Female& 19&  8&391&244&299&317\tabularnewline
\hline
\end{tabular}

\end{center}

 > ft1 <- ftable(UCBAdmissions, col.vars=2:3)
 > ft1
          Gender Male                     Female
          Dept      A   B   C   D   E   F      A   B   C   D   E   F
Admit
Admitted         512 353 120 138  53  22     89  17 202 131  94  24
Rejected         313 207 205 279 138 351     19   8 391 244 299 317
 >
 > latex(ft1, file="")
Error in rv[[2]] : subscript out of bounds
 >
On 12/2/2010 5:24 PM, RICHARD M. HEIBERGER wrote: