]> git.donarmstrong.com Git - xtable.git/commitdiff
Changes to print.xtable() vectorizing some of the formatting code.
authorroosen <roosen@edb9625f-4e0d-4859-8d74-9fd3b1da38cb>
Tue, 6 Dec 2011 07:34:26 +0000 (07:34 +0000)
committerroosen <roosen@edb9625f-4e0d-4859-8d74-9fd3b1da38cb>
Tue, 6 Dec 2011 07:34:26 +0000 (07:34 +0000)
git-svn-id: svn://scm.r-forge.r-project.org/svnroot/xtable@17 edb9625f-4e0d-4859-8d74-9fd3b1da38cb

pkg/R/print.xtable.R

index 43fb044f772bea3bcc837f468768a5a370641d36..c20fb6212a31c92b07ab8e1538692a145058bdb9 100644 (file)
-### xtable package
-###
-### Produce LaTeX and HTML tables from R objects.
-###
-### Copyright 2000-2007 David B. Dahl <dahl@stat.tamu.edu>
-###
-### This file is part of the `xtable' library for R and related languages.
-### It is made available under the terms of the GNU General Public
-### License, version 2, or at your option, any later version,
-### incorporated herein by reference.
-###
-### This program is distributed in the hope that it will be
-### useful, but WITHOUT ANY WARRANTY; without even the implied
-### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-### PURPOSE.  See the GNU General Public License for more
-### details.
-###
-### You should have received a copy of the GNU General Public
-### License along with this program; if not, write to the Free
-### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-### MA 02111-1307, USA
-print.xtable <- function(
-  x,
-  type="latex",
-  file="",
-  append=FALSE,
-  floating=TRUE,
-  floating.environment="table",
-  table.placement="ht",
-  caption.placement="bottom",
-  latex.environments=c("center"),
-  tabular.environment="tabular",
-  size=NULL,
-  hline.after=c(-1,0,nrow(x)),
-  NA.string="",
-  include.rownames=TRUE,
-  include.colnames=TRUE,
-  only.contents=FALSE,
-  add.to.row=NULL,
-  sanitize.text.function=NULL,
-  sanitize.rownames.function=sanitize.text.function,
-  sanitize.colnames.function=sanitize.text.function,
-  math.style.negative=FALSE,
-  html.table.attributes="border=1",
-  ...) {
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 hline.after
-  # By default it print an \hline before and after the columns names independently they are printed or not and at the end of the table
-  # Old code that set hline.after should include c(-1, 0, nrow(x)) in the hline.after vector
-  # If you do not want any \hline inside the data, set hline.after to NULL 
-  # PHEADER instead the string '\\hline\n' is used in the code
-  # Now hline.after counts how many time a position appear  
-  # I left an automatic PHEADER in the longtable is this correct?
-
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 include.rownames, include.colnames  
-  pos <- 0
-  if (include.rownames) pos <- 1
-  
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 hline.after checks
-  if (any(hline.after < -1) | any(hline.after > nrow(x))) stop("'hline.after' must be inside [-1, nrow(x)]")
-  
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 add.to.row checks
-  if (!is.null(add.to.row)) {
-    if (is.list(add.to.row) && length(add.to.row)==2) {
-      if (is.null(names(add.to.row))) {
-        names(add.to.row) <- c('pos', 'command')
-      } else if (any(sort(names(add.to.row))!=c('command', 'pos'))) {
-        stop("the names of the elements of 'add.to.row' must be 'pos' and 'command'")
-      }
-      if (is.list(add.to.row$pos) && is.vector(add.to.row$command, mode='character')) {
-        if ((npos <- length(add.to.row$pos)) != length(add.to.row$command)) {
-          stop("the length of 'add.to.row$pos' must be equal to the length of 'add.to.row$command'")
-        }
-        if (any(unlist(add.to.row$pos) < -1) | any(unlist(add.to.row$pos) > nrow(x))) {
-          stop("the values in add.to.row$pos must be inside the interval [-1, nrow(x)]")
-        }
-      } else {
-        stop("the first argument ('pos') of 'add.to.row' must be a list, the second argument ('command') must be a vector of mode character")
-      }
-    } else {
-      stop("'add.to.row' argument must be a list of length 2")
-    }
-  } else {
-     add.to.row <- list(pos=list(), command=vector(length=0, mode="character"))
-     npos <- 0
-  }
-
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 add.to.row
-  # Add further commands at the end of rows
-  if (type=="latex") {
-     PHEADER <- "\\hline\n"
-  } else {
-     PHEADER <- ""
-  }
-   
-  lastcol <- rep(" ", nrow(x)+2)
-  if (!is.null(hline.after)) {
-     add.to.row$pos[[npos+1]] <- hline.after
-     add.to.row$command <- c(add.to.row$command, PHEADER)
-  }
-  if ( length(add.to.row$command) > 0 ) {
-    for (i in 1:length(add.to.row$command)) {
-      addpos <- add.to.row$pos[[i]]
-      freq <- table(addpos)
-      addpos <- unique(addpos)
-      for (j in 1:length(addpos)) {
-        lastcol[addpos[j]+2] <- paste(lastcol[addpos[j]+2], paste(rep(add.to.row$command[i], freq[j]), sep="", collapse=""), sep=" ")
-      }
-    }
-  }
-  
-  if (length(type)>1) stop("\"type\" must have length 1")
-  type <- tolower(type)
-  if (!all(!is.na(match(type,c("latex","html"))))) stop("\"type\" must be in {\"latex\", \"html\"}")
-  if (!all(!is.na(match(floating.environment,c("table","table*","sidewaystable"))))) stop("\"type\" must be in {\"table\", \"table*\", \"sidewaystable\"}")
-  if (!all(!is.na(match(unlist(strsplit(table.placement, split="")),c("H","h","t","b","p","!"))))) {
-    stop("\"table.placement\" must contain only elements of {\"h\",\"t\",\"b\",\"p\",\"!\"}")
-  }
-  if (!all(!is.na(match(caption.placement,c("bottom","top"))))) stop("\"caption.placement\" must be either {\"bottom\",\"top\"}")
-
-  if (type=="latex") {
-    BCOMMENT <- "% "
-    ECOMMENT <- "\n"
-    # See e-mail from "John S. Walker <jsw9c@uic.edu>" dated 5-19-2003 regarding "texfloat"
-    # See e-mail form "Fernando Henrique Ferraz P. da Rosa" <academic@feferraz.net>" dated 10-28-2005 regarding "longtable"
-    if ( tabular.environment == "longtable" & floating == TRUE ) {
-      warning("Attempt to use \"longtable\" with floating=TRUE. Changing to FALSE.")
-      floating <- FALSE
-    }
-    if ( floating == TRUE ) {
-      # See e-mail from "Pfaff, Bernhard <Bernhard.Pfaff@drkw.com>" dated 7-09-2003 regarding "suggestion for an amendment of the source"
-      # See e-mail from "Mitchell, David" <David.Mitchell@dotars.gov.au>" dated 2003-07-09 regarding "Additions to R xtable package"
-      # See e-mail from "Garbade, Sven" <Sven.Garbade@med.uni-heidelberg.de> dated 2006-05-22 regarding the floating environment.
-      BTABLE <- paste("\\begin{", floating.environment, "}",ifelse(!is.null(table.placement),
-        paste("[",table.placement,"]",sep=""),""),"\n",sep="")
-      if ( is.null(latex.environments) || (length(latex.environments)==0) ) {
-        BENVIRONMENT <- ""
-        EENVIRONMENT <- ""
-      }
-      else {
-        BENVIRONMENT <- ""
-        EENVIRONMENT <- ""
-        for ( i in 1:length(latex.environments) ) {
-          if ( latex.environments[i] == "" ) next
-          BENVIRONMENT <- paste(BENVIRONMENT, "\\begin{",latex.environments[i],"}\n",sep="")
-          EENVIRONMENT <- paste("\\end{",latex.environments[i],"}\n",EENVIRONMENT,sep="")
-        }
-      }
-      ETABLE <- paste("\\end{", floating.environment, "}\n", sep="")
-    }
-    else {
-      BTABLE <- ""
-      ETABLE <- ""
-      BENVIRONMENT <- ""
-      EENVIRONMENT <- ""
-    }
-
-    tmp.index.start <- 1
-    if ( ! include.rownames ) {
-      while ( attr(x,"align",exact=TRUE)[tmp.index.start] == '|' ) tmp.index.start <- tmp.index.start + 1
-      tmp.index.start <- tmp.index.start + 1
-    }
-    BTABULAR <- paste("\\begin{",tabular.environment,"}{",
-                      paste(c(attr(x, "align",exact=TRUE)[tmp.index.start:length(attr(x,"align",exact=TRUE))], "}\n"),
-                            sep="", collapse=""),
-                      sep="")
-    
-    ## fix 10-26-09 (robert.castelo@upf.edu) the following 'if' condition is added here to support
-    ## a caption on the top of a longtable
-    if (tabular.environment == "longtable" && caption.placement=="top") {
-        BCAPTION <- "\\caption{"
-        ECAPTION <- "} \\\\ \n"
-        if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="latex")) BTABULAR <- paste(BTABULAR,  BCAPTION, attr(x,"caption",exact=TRUE), ECAPTION, sep="")
-    }
-    # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 add.to.row position -1
-    BTABULAR <- paste(BTABULAR,lastcol[1], sep="")
-    # the \hline at the end, if present, is set in full matrix    
-    ETABULAR <- paste("\\end{",tabular.environment,"}\n",sep="")
-    
-    # BSIZE contributed by Benno <puetz@mpipsykl.mpg.de> in e-mail dated Wednesday, December 01, 2004
-    if (is.null(size) || !is.character(size)) {
-      BSIZE <- ""
-      ESIZE <- ""
-    } else {
-      if(length(grep("^\\\\",size))==0){
-        size <- paste("\\",size,sep="")
-      }
-      BSIZE <- paste("{",size,"\n",sep="")
-      ESIZE <- "}\n"
-    }
-    BLABEL <- "\\label{"
-    ELABEL <- "}\n"
-    BCAPTION <- "\\caption{"
-    ECAPTION <- "}\n"
-    BROW <- ""
-    EROW <- " \\\\ \n"
-    BTH <- ""
-    ETH <- ""
-    STH <- " & "
-    BTD1 <- " & "
-    BTD2 <- ""
-    BTD3 <- ""
-    ETD  <- ""
-    # Based on contribution from Jonathan Swinton <jonathan@swintons.net> in e-mail dated Wednesday, January 17, 2007
-    sanitize <- function(str) {
-      result <- str
-      result <- gsub("\\\\","SANITIZE.BACKSLASH",result)
-      result <- gsub("$","\\$",result,fixed=TRUE)
-      result <- gsub(">","$>$",result,fixed=TRUE)
-      result <- gsub("<","$<$",result,fixed=TRUE)
-      result <- gsub("|","$|$",result,fixed=TRUE)
-      result <- gsub("{","\\{",result,fixed=TRUE)
-      result <- gsub("}","\\}",result,fixed=TRUE)
-      result <- gsub("%","\\%",result,fixed=TRUE)
-      result <- gsub("&","\\&",result,fixed=TRUE)
-      result <- gsub("_","\\_",result,fixed=TRUE)
-      result <- gsub("#","\\#",result,fixed=TRUE)
-      result <- gsub("^","\\verb|^|",result,fixed=TRUE)
-      result <- gsub("~","\\~{}",result,fixed=TRUE)
-      result <- gsub("SANITIZE.BACKSLASH","$\\backslash$",result,fixed=TRUE)
-      return(result)
-    }
-    sanitize.numbers <- function(x) {
-      result <- x
-      if ( math.style.negative ) {
-        # Jake Bowers <jwbowers@illinois.edu> in e-mail from 2008-08-20 suggested
-        # disabling this feature to avoid problems with LaTeX's dcolumn package.
-        # by Florian Wickelmaier <florian.wickelmaier@uni-tuebingen.de> in e-mail
-        # from 2008-10-03 requested the ability to use the old behavior.
-        for(i in 1:length(x)) {
-          result[i] <- gsub("-","$-$",result[i],fixed=TRUE)
-        }
-      }
-      return(result)
-    }
-    sanitize.final <- function(result) {
-      return(result)
-    }
-  } else {
-    BCOMMENT <- "<!-- "
-    ECOMMENT <- " -->\n"
-    BTABLE <- paste("<TABLE ",html.table.attributes,">\n",sep="")
-    ETABLE <- "</TABLE>\n"
-    BENVIRONMENT <- ""
-    EENVIRONMENT <- ""
-    BTABULAR <- ""
-    ETABULAR <- ""
-    BSIZE <- ""
-    ESIZE <- ""
-    BLABEL <- "<A NAME="
-    ELABEL <- "></A>\n"
-    BCAPTION <- paste("<CAPTION ALIGN=\"",caption.placement,"\"> ",sep="")
-    ECAPTION <- " </CAPTION>\n"
-    BROW <- "<TR>"
-    EROW <- " </TR>\n"
-    BTH <- " <TH> "
-    ETH <- " </TH> "
-    STH <- " </TH> <TH> "
-    BTD1 <- " <TD align=\""
-    align.tmp <- attr(x,"align",exact=TRUE)
-    align.tmp <- align.tmp[align.tmp!="|"]
-    BTD2 <- matrix(align.tmp[(2-pos):(ncol(x)+1)],nrow=nrow(x),ncol=ncol(x)+pos,byrow=TRUE)
-    # Based on contribution from Jonathan Swinton <jonathan@swintons.net> in e-mail dated Wednesday, January 17, 2007
-    BTD2[regexpr("^p",BTD2)>0] <- "left"
-    BTD2[BTD2=="r"] <- "right"
-    BTD2[BTD2=="l"] <- "left"
-    BTD2[BTD2=="c"] <- "center"
-    BTD3 <- "\"> "
-    ETD  <- " </TD>"
-    sanitize <- function(str) {
-      result <- str
-      result <- gsub("&","&amp ",result,fixed=TRUE)
-      result <- gsub(">","&gt ",result,fixed=TRUE)
-      result <- gsub("<","&lt ",result,fixed=TRUE)
-      # Kurt Hornik <Kurt.Hornik@wu-wien.ac.at> on 2006/10/05 recommended not escaping underscores.
-      # result <- gsub("_", "\\_", result, fixed=TRUE)
-      return(result)
-    }
-    sanitize.numbers <- function(x) {
-      return(x)
-    }
-    sanitize.final <- function(result) {
-      # Suggested by Uwe Ligges <ligges@statistik.uni-dortmund.de> in e-mail dated 2005-07-30.
-      result$text <- gsub("  *"," ", result$text,fixed=TRUE)
-      result$text <- gsub(' align="left"', "", result$text,fixed=TRUE)
-      return(result)
-    }
-  }
-
-  result <- string("",file=file,append=append)
-  info <- R.Version()
-  # modified Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 to set automatically the package version
-  result <- result + BCOMMENT + type + " table generated in " +
-            info$language + " " + info$major + "." + info$minor + " by xtable " + packageDescription('xtable')$Version + " package" + ECOMMENT
-  result <- result + BCOMMENT + date() + ECOMMENT
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 only.contents
-  if (!only.contents) {
-    result <- result + BTABLE
-    result <- result + BENVIRONMENT
-    if ( floating == TRUE ) {
-      if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="html" || caption.placement=="top")) result <- result + BCAPTION + attr(x,"caption",exact=TRUE) + ECAPTION
-      if (!is.null(attr(x,"label",exact=TRUE)) && (type=="latex" && caption.placement=="top")) result <- result + BLABEL + attr(x,"label",exact=TRUE) + ELABEL  
-    }
-    result <- result + BSIZE
-    result <- result + BTABULAR
-  }
-  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 include.colnames, include.rownames 
-  if (include.colnames) {
-    result <- result + BROW + BTH
-    if (include.rownames) result <- result + STH
-    if (is.null(sanitize.colnames.function)) {                                     # David G. Whiting in e-mail 2007-10-09
-      result <- result + paste(sanitize(names(x)),collapse=STH)
-    } else {
-      result <- result + paste(sanitize.colnames.function(names(x)), collapse=STH) # David G. Whiting in e-mail 2007-10-09
-    }
-    result <- result + ETH + EROW
-  }
-
-  cols <- matrix("",nrow=nrow(x),ncol=ncol(x)+pos)
-  if (include.rownames) {
-    if (is.null(sanitize.rownames.function)) {                                     # David G. Whiting in e-mail 2007-10-09
-      cols[,1] <- sanitize(row.names(x))
-    } else {
-      cols[,1] <- sanitize.rownames.function(row.names(x))                         # David G. Whiting in e-mail 2007-10-09
-    }
-  }
-
-  disp <- function(y) {
-    if (is.factor(y)) {
-      y <- levels(y)[y]
-    }
-    if (is.list(y)) {
-      y <- unlist(y)
-    }
-    return(y)
-  }
-  # Code for letting "digits" be a matrix was provided by Arne Henningsen <ahenningsen@agric-econ.uni-kiel.de> in e-mail dated 2005-06-04.
-  if( !is.matrix( attr( x, "digits",exact=TRUE ) ) ) {
-    # modified Claudio Agostinelli <claudio@unive.it> dated 2006-07-28
-    attr(x,"digits") <- matrix( attr( x, "digits",exact=TRUE ), nrow = nrow(x), ncol = ncol(x)+1, byrow = TRUE )
-  }
-  for(i in 1:ncol(x)) {
-    ina <- is.na(x[,i])
-    is.numeric.column <- is.numeric(x[,i])
-    for( j in 1:nrow( cols ) ) {
-      ### modified Claudio Agostinelli <claudio@unive.it> dated 2009-09-14
-      ### add decimal.mark=options()$OutDec
-      cols[j,i+pos] <-
-        formatC( disp( x[j,i] ),
-          format = ifelse( attr( x, "digits",exact=TRUE )[j,i+1] < 0, "E", attr( x, "display",exact=TRUE )[i+1] ), digits = abs( attr( x, "digits",exact=TRUE )[j,i+1] ), decimal.mark=options()$OutDec)
-    }
-    if ( any(ina) ) cols[ina,i+pos] <- NA.string
-    # Based on contribution from Jonathan Swinton <jonathan@swintons.net> in e-mail dated Wednesday, January 17, 2007
-    if ( is.numeric.column ) {
-      cols[,i+pos] <- sanitize.numbers(cols[,i+pos])
-    } else {
-      if (is.null(sanitize.text.function)) {
-        cols[,i+pos] <- sanitize(cols[,i+pos])
-      } else {
-        cols[,i+pos] <- sanitize.text.function(cols[,i+pos])
-      }
-    }
-  }
-
-  multiplier <- 5
-  full <- matrix("",nrow=nrow(x),ncol=multiplier*(ncol(x)+pos)+2)
-  full[,1] <- BROW
-  full[,multiplier*(0:(ncol(x)+pos-1))+2] <- BTD1
-  full[,multiplier*(0:(ncol(x)+pos-1))+3] <- BTD2
-  full[,multiplier*(0:(ncol(x)+pos-1))+4] <- BTD3
-  full[,multiplier*(0:(ncol(x)+pos-1))+5] <- cols
-  full[,multiplier*(0:(ncol(x)+pos-1))+6] <- ETD
-
-  full[,multiplier*(ncol(x)+pos)+2] <- paste(EROW, lastcol[-(1:2)], sep=" ")
-  if (type=="latex") full[,2] <- ""
-  result <- result + lastcol[2] + paste(t(full),collapse="")
-  if (!only.contents) {
-    if (tabular.environment == "longtable") {
-      result <- result + PHEADER
-      ## fix 10-27-09 Liviu Andronic (landronimirc@gmail.com) the following 'if' condition is inserted in order to avoid
-      ## that bottom caption interferes with a top caption of a longtable
-      if(caption.placement=="bottom"){
-        if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="latex")) result <- result + BCAPTION + attr(x,"caption",exact=TRUE) + ECAPTION
-      }
-      if (!is.null(attr(x,"label",exact=TRUE))) result <- result + BLABEL + attr(x,"label",exact=TRUE) + ELABEL
-      ETABULAR <- "\\end{longtable}\n"
-    }
-    result <- result + ETABULAR
-    result <- result + ESIZE
-    if ( floating == TRUE ) {
-      if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="latex" && caption.placement=="bottom")) result <- result + BCAPTION + attr(x,"caption",exact=TRUE) + ECAPTION
-      if (!is.null(attr(x,"label",exact=TRUE)) && caption.placement=="bottom") result <- result + BLABEL + attr(x,"label",exact=TRUE) + ELABEL  
-    }
-    result <- result + EENVIRONMENT
-    result <- result + ETABLE
-  }   
-  result <- sanitize.final(result)
-  print(result)
-
-  return(invisible(result$text))
-}
-
-"+.string" <- function(x,y) {
-  x$text <- paste(x$text,as.string(y)$text,sep="")
-  return(x)
-}
-
-print.string <- function(x,...) {
-  cat(x$text,file=x$file,append=x$append)
-  return(invisible())
-}
-
-string <- function(text,file="",append=FALSE) {
-  x <- list(text=text,file=file,append=append)
-  class(x) <- "string"
-  return(x)
-}
-
-as.string <- function(x,file="",append=FALSE) {
-  if (is.null(attr(x,"class",exact=TRUE)))
-  switch(data.class(x),
-      character=return(string(x,file,append)),
-      numeric=return(string(as.character(x),file,append)),
-      stop("Cannot coerse argument to a string"))
-  if (class(x)=="string")
-    return(x)
-  stop("Cannot coerse argument to a string")
-}
-
-is.string <- function(x) {
-  return(class(x)=="string")
-}
-
+### xtable package\r
+###\r
+### Produce LaTeX and HTML tables from R objects.\r
+###\r
+### Copyright 2000-2012 David B. Dahl <dahl@stat.tamu.edu>\r
+###\r
+### Maintained by Charles Roosen <croosen@mango-solutions.com>\r
+###\r
+### This file is part of the `xtable' library for R and related languages.\r
+### It is made available under the terms of the GNU General Public\r
+### License, version 2, or at your option, any later version,\r
+### incorporated herein by reference.\r
+###\r
+### This program is distributed in the hope that it will be\r
+### useful, but WITHOUT ANY WARRANTY; without even the implied\r
+### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+### PURPOSE.  See the GNU General Public License for more\r
+### details.\r
+###\r
+### You should have received a copy of the GNU General Public\r
+### License along with this program; if not, write to the Free\r
+### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,\r
+### MA 02111-1307, USA\r
+print.xtable <- function(\r
+  x,\r
+  type="latex",\r
+  file="",\r
+  append=FALSE,\r
+  floating=TRUE,\r
+  floating.environment="table",\r
+  table.placement="ht",\r
+  caption.placement="bottom",\r
+  latex.environments=c("center"),\r
+  tabular.environment="tabular",\r
+  size=NULL,\r
+  hline.after=c(-1,0,nrow(x)),\r
+  NA.string="",\r
+  include.rownames=TRUE,\r
+  include.colnames=TRUE,\r
+  only.contents=FALSE,\r
+  add.to.row=NULL,\r
+  sanitize.text.function=NULL,\r
+  sanitize.rownames.function=sanitize.text.function,\r
+  sanitize.colnames.function=sanitize.text.function,\r
+  math.style.negative=FALSE,\r
+  html.table.attributes="border=1",\r
+  ...) {\r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 hline.after\r
+  # By default it print an \hline before and after the columns names independently they are printed or not and at the end of the table\r
+  # Old code that set hline.after should include c(-1, 0, nrow(x)) in the hline.after vector\r
+  # If you do not want any \hline inside the data, set hline.after to NULL \r
+  # PHEADER instead the string '\\hline\n' is used in the code\r
+  # Now hline.after counts how many time a position appear  \r
+  # I left an automatic PHEADER in the longtable is this correct?\r
+\r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 include.rownames, include.colnames  \r
+  pos <- 0\r
+  if (include.rownames) pos <- 1\r
+  \r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 hline.after checks\r
+  if (any(hline.after < -1) | any(hline.after > nrow(x))) stop("'hline.after' must be inside [-1, nrow(x)]")\r
+  \r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 add.to.row checks\r
+  if (!is.null(add.to.row)) {\r
+    if (is.list(add.to.row) && length(add.to.row)==2) {\r
+      if (is.null(names(add.to.row))) {\r
+        names(add.to.row) <- c('pos', 'command')\r
+      } else if (any(sort(names(add.to.row))!=c('command', 'pos'))) {\r
+        stop("the names of the elements of 'add.to.row' must be 'pos' and 'command'")\r
+      }\r
+      if (is.list(add.to.row$pos) && is.vector(add.to.row$command, mode='character')) {\r
+        if ((npos <- length(add.to.row$pos)) != length(add.to.row$command)) {\r
+          stop("the length of 'add.to.row$pos' must be equal to the length of 'add.to.row$command'")\r
+        }\r
+        if (any(unlist(add.to.row$pos) < -1) | any(unlist(add.to.row$pos) > nrow(x))) {\r
+          stop("the values in add.to.row$pos must be inside the interval [-1, nrow(x)]")\r
+        }\r
+      } else {\r
+        stop("the first argument ('pos') of 'add.to.row' must be a list, the second argument ('command') must be a vector of mode character")\r
+      }\r
+    } else {\r
+      stop("'add.to.row' argument must be a list of length 2")\r
+    }\r
+  } else {\r
+     add.to.row <- list(pos=list(), command=vector(length=0, mode="character"))\r
+     npos <- 0\r
+  }\r
+\r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 add.to.row\r
+  # Add further commands at the end of rows\r
+  if (type=="latex") {\r
+     PHEADER <- "\\hline\n"\r
+  } else {\r
+     PHEADER <- ""\r
+  }\r
+   \r
+  lastcol <- rep(" ", nrow(x)+2)\r
+  if (!is.null(hline.after)) {\r
+     add.to.row$pos[[npos+1]] <- hline.after\r
+     add.to.row$command <- c(add.to.row$command, PHEADER)\r
+  }\r
+  if ( length(add.to.row$command) > 0 ) {\r
+    for (i in 1:length(add.to.row$command)) {\r
+      addpos <- add.to.row$pos[[i]]\r
+      freq <- table(addpos)\r
+      addpos <- unique(addpos)\r
+      for (j in 1:length(addpos)) {\r
+        lastcol[addpos[j]+2] <- paste(lastcol[addpos[j]+2], paste(rep(add.to.row$command[i], freq[j]), sep="", collapse=""), sep=" ")\r
+      }\r
+    }\r
+  }\r
+  \r
+  if (length(type)>1) stop("\"type\" must have length 1")\r
+  type <- tolower(type)\r
+  if (!all(!is.na(match(type,c("latex","html"))))) stop("\"type\" must be in {\"latex\", \"html\"}")\r
+  if (!all(!is.na(match(floating.environment,c("table","table*","sidewaystable"))))) stop("\"type\" must be in {\"table\", \"table*\", \"sidewaystable\"}")\r
+  if (!all(!is.na(match(unlist(strsplit(table.placement, split="")),c("H","h","t","b","p","!"))))) {\r
+    stop("\"table.placement\" must contain only elements of {\"h\",\"t\",\"b\",\"p\",\"!\"}")\r
+  }\r
+  if (!all(!is.na(match(caption.placement,c("bottom","top"))))) stop("\"caption.placement\" must be either {\"bottom\",\"top\"}")\r
+\r
+  if (type=="latex") {\r
+    BCOMMENT <- "% "\r
+    ECOMMENT <- "\n"\r
+    # See e-mail from "John S. Walker <jsw9c@uic.edu>" dated 5-19-2003 regarding "texfloat"\r
+    # See e-mail form "Fernando Henrique Ferraz P. da Rosa" <academic@feferraz.net>" dated 10-28-2005 regarding "longtable"\r
+    if ( tabular.environment == "longtable" & floating == TRUE ) {\r
+      warning("Attempt to use \"longtable\" with floating=TRUE. Changing to FALSE.")\r
+      floating <- FALSE\r
+    }\r
+    if ( floating == TRUE ) {\r
+      # See e-mail from "Pfaff, Bernhard <Bernhard.Pfaff@drkw.com>" dated 7-09-2003 regarding "suggestion for an amendment of the source"\r
+      # See e-mail from "Mitchell, David" <David.Mitchell@dotars.gov.au>" dated 2003-07-09 regarding "Additions to R xtable package"\r
+      # See e-mail from "Garbade, Sven" <Sven.Garbade@med.uni-heidelberg.de> dated 2006-05-22 regarding the floating environment.\r
+      BTABLE <- paste("\\begin{", floating.environment, "}",ifelse(!is.null(table.placement),\r
+        paste("[",table.placement,"]",sep=""),""),"\n",sep="")\r
+      if ( is.null(latex.environments) || (length(latex.environments)==0) ) {\r
+        BENVIRONMENT <- ""\r
+        EENVIRONMENT <- ""\r
+      }\r
+      else {\r
+        BENVIRONMENT <- ""\r
+        EENVIRONMENT <- ""\r
+        for ( i in 1:length(latex.environments) ) {\r
+          if ( latex.environments[i] == "" ) next\r
+          BENVIRONMENT <- paste(BENVIRONMENT, "\\begin{",latex.environments[i],"}\n",sep="")\r
+          EENVIRONMENT <- paste("\\end{",latex.environments[i],"}\n",EENVIRONMENT,sep="")\r
+        }\r
+      }\r
+      ETABLE <- paste("\\end{", floating.environment, "}\n", sep="")\r
+    }\r
+    else {\r
+      BTABLE <- ""\r
+      ETABLE <- ""\r
+      BENVIRONMENT <- ""\r
+      EENVIRONMENT <- ""\r
+    }\r
+\r
+    tmp.index.start <- 1\r
+    if ( ! include.rownames ) {\r
+      while ( attr(x,"align",exact=TRUE)[tmp.index.start] == '|' ) tmp.index.start <- tmp.index.start + 1\r
+      tmp.index.start <- tmp.index.start + 1\r
+    }\r
+    BTABULAR <- paste("\\begin{",tabular.environment,"}{",\r
+                      paste(c(attr(x, "align",exact=TRUE)[tmp.index.start:length(attr(x,"align",exact=TRUE))], "}\n"),\r
+                            sep="", collapse=""),\r
+                      sep="")\r
+    \r
+    ## fix 10-26-09 (robert.castelo@upf.edu) the following 'if' condition is added here to support\r
+    ## a caption on the top of a longtable\r
+    if (tabular.environment == "longtable" && caption.placement=="top") {\r
+        BCAPTION <- "\\caption{"\r
+        ECAPTION <- "} \\\\ \n"\r
+        if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="latex")) BTABULAR <- paste(BTABULAR,  BCAPTION, attr(x,"caption",exact=TRUE), ECAPTION, sep="")\r
+    }\r
+    # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 add.to.row position -1\r
+    BTABULAR <- paste(BTABULAR,lastcol[1], sep="")\r
+    # the \hline at the end, if present, is set in full matrix    \r
+    ETABULAR <- paste("\\end{",tabular.environment,"}\n",sep="")\r
+    \r
+    # BSIZE contributed by Benno <puetz@mpipsykl.mpg.de> in e-mail dated Wednesday, December 01, 2004\r
+    if (is.null(size) || !is.character(size)) {\r
+      BSIZE <- ""\r
+      ESIZE <- ""\r
+    } else {\r
+      if(length(grep("^\\\\",size))==0){\r
+        size <- paste("\\",size,sep="")\r
+      }\r
+      BSIZE <- paste("{",size,"\n",sep="")\r
+      ESIZE <- "}\n"\r
+    }\r
+    BLABEL <- "\\label{"\r
+    ELABEL <- "}\n"\r
+    BCAPTION <- "\\caption{"\r
+    ECAPTION <- "}\n"\r
+    BROW <- ""\r
+    EROW <- " \\\\ \n"\r
+    BTH <- ""\r
+    ETH <- ""\r
+    STH <- " & "\r
+    BTD1 <- " & "\r
+    BTD2 <- ""\r
+    BTD3 <- ""\r
+    ETD  <- ""\r
+    # Based on contribution from Jonathan Swinton <jonathan@swintons.net> in e-mail dated Wednesday, January 17, 2007\r
+    sanitize <- function(str) {\r
+      result <- str\r
+      result <- gsub("\\\\","SANITIZE.BACKSLASH",result)\r
+      result <- gsub("$","\\$",result,fixed=TRUE)\r
+      result <- gsub(">","$>$",result,fixed=TRUE)\r
+      result <- gsub("<","$<$",result,fixed=TRUE)\r
+      result <- gsub("|","$|$",result,fixed=TRUE)\r
+      result <- gsub("{","\\{",result,fixed=TRUE)\r
+      result <- gsub("}","\\}",result,fixed=TRUE)\r
+      result <- gsub("%","\\%",result,fixed=TRUE)\r
+      result <- gsub("&","\\&",result,fixed=TRUE)\r
+      result <- gsub("_","\\_",result,fixed=TRUE)\r
+      result <- gsub("#","\\#",result,fixed=TRUE)\r
+      result <- gsub("^","\\verb|^|",result,fixed=TRUE)\r
+      result <- gsub("~","\\~{}",result,fixed=TRUE)\r
+      result <- gsub("SANITIZE.BACKSLASH","$\\backslash$",result,fixed=TRUE)\r
+      return(result)\r
+    }\r
+    sanitize.numbers <- function(x) {\r
+      result <- x\r
+      if ( math.style.negative ) {\r
+        # Jake Bowers <jwbowers@illinois.edu> in e-mail from 2008-08-20 suggested\r
+        # disabling this feature to avoid problems with LaTeX's dcolumn package.\r
+        # by Florian Wickelmaier <florian.wickelmaier@uni-tuebingen.de> in e-mail\r
+        # from 2008-10-03 requested the ability to use the old behavior.\r
+        for(i in 1:length(x)) {\r
+          result[i] <- gsub("-","$-$",result[i],fixed=TRUE)\r
+        }\r
+      }\r
+      return(result)\r
+    }\r
+    sanitize.final <- function(result) {\r
+      return(result)\r
+    }\r
+  } else {\r
+    BCOMMENT <- "<!-- "\r
+    ECOMMENT <- " -->\n"\r
+    BTABLE <- paste("<TABLE ",html.table.attributes,">\n",sep="")\r
+    ETABLE <- "</TABLE>\n"\r
+    BENVIRONMENT <- ""\r
+    EENVIRONMENT <- ""\r
+    BTABULAR <- ""\r
+    ETABULAR <- ""\r
+    BSIZE <- ""\r
+    ESIZE <- ""\r
+    BLABEL <- "<A NAME="\r
+    ELABEL <- "></A>\n"\r
+    BCAPTION <- paste("<CAPTION ALIGN=\"",caption.placement,"\"> ",sep="")\r
+    ECAPTION <- " </CAPTION>\n"\r
+    BROW <- "<TR>"\r
+    EROW <- " </TR>\n"\r
+    BTH <- " <TH> "\r
+    ETH <- " </TH> "\r
+    STH <- " </TH> <TH> "\r
+    BTD1 <- " <TD align=\""\r
+    align.tmp <- attr(x,"align",exact=TRUE)\r
+    align.tmp <- align.tmp[align.tmp!="|"]\r
+    BTD2 <- matrix(align.tmp[(2-pos):(ncol(x)+1)],nrow=nrow(x),ncol=ncol(x)+pos,byrow=TRUE)\r
+    # Based on contribution from Jonathan Swinton <jonathan@swintons.net> in e-mail dated Wednesday, January 17, 2007\r
+    BTD2[regexpr("^p",BTD2)>0] <- "left"\r
+    BTD2[BTD2=="r"] <- "right"\r
+    BTD2[BTD2=="l"] <- "left"\r
+    BTD2[BTD2=="c"] <- "center"\r
+    BTD3 <- "\"> "\r
+    ETD  <- " </TD>"\r
+    sanitize <- function(str) {\r
+      result <- str\r
+      result <- gsub("&","&amp ",result,fixed=TRUE)\r
+      result <- gsub(">","&gt ",result,fixed=TRUE)\r
+      result <- gsub("<","&lt ",result,fixed=TRUE)\r
+      # Kurt Hornik <Kurt.Hornik@wu-wien.ac.at> on 2006/10/05 recommended not escaping underscores.\r
+      # result <- gsub("_", "\\_", result, fixed=TRUE)\r
+      return(result)\r
+    }\r
+    sanitize.numbers <- function(x) {\r
+      return(x)\r
+    }\r
+    sanitize.final <- function(result) {\r
+      # Suggested by Uwe Ligges <ligges@statistik.uni-dortmund.de> in e-mail dated 2005-07-30.\r
+      result$text <- gsub("  *"," ", result$text,fixed=TRUE)\r
+      result$text <- gsub(' align="left"', "", result$text,fixed=TRUE)\r
+      return(result)\r
+    }\r
+  }\r
+\r
+  result <- string("",file=file,append=append)\r
+  info <- R.Version()\r
+  # modified Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 to set automatically the package version\r
+  result <- result + BCOMMENT + type + " table generated in " +\r
+            info$language + " " + info$major + "." + info$minor + " by xtable " + packageDescription('xtable')$Version + " package" + ECOMMENT\r
+  result <- result + BCOMMENT + date() + ECOMMENT\r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 only.contents\r
+  if (!only.contents) {\r
+    result <- result + BTABLE\r
+    result <- result + BENVIRONMENT\r
+    if ( floating == TRUE ) {\r
+      if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="html" || caption.placement=="top")) result <- result + BCAPTION + attr(x,"caption",exact=TRUE) + ECAPTION\r
+      if (!is.null(attr(x,"label",exact=TRUE)) && (type=="latex" && caption.placement=="top")) result <- result + BLABEL + attr(x,"label",exact=TRUE) + ELABEL  \r
+    }\r
+    result <- result + BSIZE\r
+    result <- result + BTABULAR\r
+  }\r
+  # Claudio Agostinelli <claudio@unive.it> dated 2006-07-28 include.colnames, include.rownames \r
+  if (include.colnames) {\r
+    result <- result + BROW + BTH\r
+    if (include.rownames) result <- result + STH\r
+    if (is.null(sanitize.colnames.function)) {                                     # David G. Whiting in e-mail 2007-10-09\r
+      result <- result + paste(sanitize(names(x)),collapse=STH)\r
+    } else {\r
+      result <- result + paste(sanitize.colnames.function(names(x)), collapse=STH) # David G. Whiting in e-mail 2007-10-09\r
+    }\r
+    result <- result + ETH + EROW\r
+  }\r
+\r
+  cols <- matrix("",nrow=nrow(x),ncol=ncol(x)+pos)\r
+  if (include.rownames) {\r
+    if (is.null(sanitize.rownames.function)) {                                     # David G. Whiting in e-mail 2007-10-09\r
+      cols[,1] <- sanitize(row.names(x))\r
+    } else {\r
+      cols[,1] <- sanitize.rownames.function(row.names(x))                         # David G. Whiting in e-mail 2007-10-09\r
+    }\r
+  }\r
+\r
+## Begin vectorizing the formatting code by Ian Fellows [ian@fellstat.com]\r
+## 06 Dec 2011\r
+##\r
+#  disp <- function(y) {\r
+#    if (is.factor(y)) {\r
+#      y <- levels(y)[y]\r
+#    }\r
+#    if (is.list(y)) {\r
+#      y <- unlist(y)\r
+#    }\r
+#    return(y)\r
+#  }\r
+  varying.digits <- is.matrix( attr( x, "digits",exact=TRUE ) )\r
+  # Code for letting "digits" be a matrix was provided by Arne Henningsen <ahenningsen@agric-econ.uni-kiel.de> in e-mail dated 2005-06-04.\r
+  #if( !varying.digits ) {\r
+    # modified Claudio Agostinelli <claudio@unive.it> dated 2006-07-28\r
+  #  attr(x,"digits") <- matrix( attr( x, "digits",exact=TRUE ), nrow = nrow(x), ncol = ncol(x)+1, byrow = TRUE )\r
+  #}\r
+  for(i in 1:ncol(x)) {\r
+       xcol <- x[,i]\r
+       if(is.factor(xcol))\r
+               xcol <- as.character(xcol)\r
+       if(is.list(xcol))\r
+               xcol <- sapply(xcol,unlist)\r
+    ina <- is.na(xcol)\r
+    is.numeric.column <- is.numeric(xcol)\r
+\r
+       if(is.character(xcol))\r
+               cols[,i+pos] <- xcol\r
+       else if(!varying.digits){\r
+               cols[,i+pos] <-\r
+                       formatC( xcol,\r
+                       format = ifelse( attr( x, "digits",exact=TRUE )[i+1] < 0, "E", \r
+                       attr( x, "display",exact=TRUE )[i+1] ), \r
+                       digits = abs( attr( x, "digits",exact=TRUE )[i+1] ), \r
+                       decimal.mark=options()$OutDec)\r
+    }else{\r
+               for( j in 1:nrow( cols ) ) {\r
+               ### modified Claudio Agostinelli <claudio@unive.it> dated 2009-09-14\r
+               ### add decimal.mark=options()$OutDec\r
+               cols[j,i+pos] <-\r
+                       formatC( xcol[j],\r
+                       format = ifelse( attr( x, "digits",exact=TRUE )[j,i+1] < 0, "E", attr( x, "display",exact=TRUE )[i+1] ), digits = abs( attr( x, "digits",exact=TRUE )[j,i+1] ), decimal.mark=options()$OutDec)\r
+               }\r
+       }\r
+       ## End Ian Fellows changes\r
+       \r
+    if ( any(ina) ) cols[ina,i+pos] <- NA.string\r
+    # Based on contribution from Jonathan Swinton <jonathan@swintons.net> in e-mail dated Wednesday, January 17, 2007\r
+    if ( is.numeric.column ) {\r
+      cols[,i+pos] <- sanitize.numbers(cols[,i+pos])\r
+    } else {\r
+      if (is.null(sanitize.text.function)) {\r
+        cols[,i+pos] <- sanitize(cols[,i+pos])\r
+      } else {\r
+        cols[,i+pos] <- sanitize.text.function(cols[,i+pos])\r
+      }\r
+    }\r
+  }\r
+\r
+  multiplier <- 5\r
+  full <- matrix("",nrow=nrow(x),ncol=multiplier*(ncol(x)+pos)+2)\r
+  full[,1] <- BROW\r
+  full[,multiplier*(0:(ncol(x)+pos-1))+2] <- BTD1\r
+  full[,multiplier*(0:(ncol(x)+pos-1))+3] <- BTD2\r
+  full[,multiplier*(0:(ncol(x)+pos-1))+4] <- BTD3\r
+  full[,multiplier*(0:(ncol(x)+pos-1))+5] <- cols\r
+  full[,multiplier*(0:(ncol(x)+pos-1))+6] <- ETD\r
+\r
+  full[,multiplier*(ncol(x)+pos)+2] <- paste(EROW, lastcol[-(1:2)], sep=" ")\r
+  if (type=="latex") full[,2] <- ""\r
+  result <- result + lastcol[2] + paste(t(full),collapse="")\r
+  if (!only.contents) {\r
+    if (tabular.environment == "longtable") {\r
+      result <- result + PHEADER\r
+      ## fix 10-27-09 Liviu Andronic (landronimirc@gmail.com) the following 'if' condition is inserted in order to avoid\r
+      ## that bottom caption interferes with a top caption of a longtable\r
+      if(caption.placement=="bottom"){\r
+        if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="latex")) result <- result + BCAPTION + attr(x,"caption",exact=TRUE) + ECAPTION\r
+      }\r
+      if (!is.null(attr(x,"label",exact=TRUE))) result <- result + BLABEL + attr(x,"label",exact=TRUE) + ELABEL\r
+      ETABULAR <- "\\end{longtable}\n"\r
+    }\r
+    result <- result + ETABULAR\r
+    result <- result + ESIZE\r
+    if ( floating == TRUE ) {\r
+      if ((!is.null(attr(x,"caption",exact=TRUE))) && (type=="latex" && caption.placement=="bottom")) result <- result + BCAPTION + attr(x,"caption",exact=TRUE) + ECAPTION\r
+      if (!is.null(attr(x,"label",exact=TRUE)) && caption.placement=="bottom") result <- result + BLABEL + attr(x,"label",exact=TRUE) + ELABEL  \r
+    }\r
+    result <- result + EENVIRONMENT\r
+    result <- result + ETABLE\r
+  }   \r
+  result <- sanitize.final(result)\r
+  print(result)\r
+\r
+  return(invisible(result$text))\r
+}\r
+\r
+"+.string" <- function(x,y) {\r
+  x$text <- paste(x$text,as.string(y)$text,sep="")\r
+  return(x)\r
+}\r
+\r
+print.string <- function(x,...) {\r
+  cat(x$text,file=x$file,append=x$append)\r
+  return(invisible())\r
+}\r
+\r
+string <- function(text,file="",append=FALSE) {\r
+  x <- list(text=text,file=file,append=append)\r
+  class(x) <- "string"\r
+  return(x)\r
+}\r
+\r
+as.string <- function(x,file="",append=FALSE) {\r
+  if (is.null(attr(x,"class",exact=TRUE)))\r
+  switch(data.class(x),\r
+      character=return(string(x,file,append)),\r
+      numeric=return(string(as.character(x),file,append)),\r
+      stop("Cannot coerse argument to a string"))\r
+  if (class(x)=="string")\r
+    return(x)\r
+  stop("Cannot coerse argument to a string")\r
+}\r
+\r
+is.string <- function(x) {\r
+  return(class(x)=="string")\r
+}\r
+\r