Skip to content

shading cells in a latex table by value

3 messages · Duncan Murdoch, Michael Friendly

#
I want to create latex tables of values where the cell background is 
shaded according to the
table value.  For example:

set.seed(1) # reproducibility
mat <- matrix(3 * rnorm(12), 3, 4)
rownames(mat) <- letters[1:3]
colnames(mat) <- LETTERS[1:4]

 > round(mat,1)
      A    B   C    D
a -1.9  4.8 1.5 -0.9
b  0.6  1.0 2.2  4.5
c -2.5 -2.5 1.7  1.2

# colors to use:  blue(+), red(-) with two shading levels,
# depending on abs(x) > 2
cols <- c(rgb(0.85,0.85,1),
           rgb(0.7 ,0.7 ,1),
           rgb(1,0.85,0.85),
           rgb(1,0.7 ,0.7 ))
cols <- matrix(cols, 2,2)

cellcol <- apply(mat, 1:2,
                  function(x) {i<-1+(x>0); j<-1+(abs(x)>2); cols[i,j]})
 >
 > cellcol
   A         B         C         D
a "#D9D9FF" "#FFB2B2" "#B2B2FF" "#D9D9FF"
b "#B2B2FF" "#B2B2FF" "#FFB2B2" "#FFB2B2"
c "#FFD9D9" "#FFD9D9" "#B2B2FF" "#B2B2FF"

What I want is to generate a latex table of mat, with each cell colored 
according to cellcol.
I can do this manually as shown below, using the latex colortbl package 
and a macro
\cell{value}{color}.  How can I produce this in R?

# colortab-test.tex -----------------------
%% Latex part:

\documentclass[11pt]{article}
\usepackage{xcolor,colortbl}

# wrap each cell with command to define background color
\newcommand{\cell}[2]{\multicolumn{1}%
    {>{\columncolor{#1}}r}{#2}}

\definecolor{blueA}{rgb}{0.85,0.85,1}
\definecolor{blueB}{rgb}{0.7 ,0.7 ,1}
\definecolor{redA}{rgb}{1,0.85,0.85}
\definecolor{redB}{rgb}{1,0.7 ,0.7 }

\begin{document}

\begin{tabular}{lcccc}
     &  A  & B  & C  & D \\
  a & \cell{-1.9}{redB} & \cell{4.8}{blueA} & \cell{1.5}{blueB} & 
\cell{-0.9}{redB} \\
  b & \cell{0.6}{blueB} & \cell{1.0}{blueB} & \cell{2.2}{blueA} &  
\cell{4.5}{blueA} \\
  c  \cell{-2.5}{redA}  & \cell{-2.5}{redB} & \cell{1.7}{blueB} &  
\cell{1.2}{blueB}  \\
\end{tabular}
\end{document}
# --------------------------------------------
#
On 23/07/2014, 9:31 AM, Michael Friendly wrote:
You could do this using the tables package, with a custom format
function.  Normally you would calculate the table entries within the
formula, but you can also convert a matrix.

For example,

colornames <- matrix(c("blueA", "blueB", "redA", "redB"),
                   2,2)

myformat <- function(x) {
  i<-1+(x>0)
  j<-1+(abs(x)>2)
  paste0("\\cell{", round(x,1), "}{", colornames[cbind(i,j)], "}")
}

tab <- as.tabular(mat, like=tabular(Heading()*row ~
Heading()*col*Format(myformat()),
                        data=data.frame(row=rep(letters[1:3],4),
                                        col=rep(LETTERS[1:4],3))))
latex(tab)

produces

\begin{tabular}{lcccc}
\hline
  & A & B & C & \multicolumn{1}{c}{D} \\
\hline
a  & \cell{-1.9}{blueA} & \cell{4.8}{redB} & \cell{1.5}{blueB} &
\cell{-0.9}{blueA} \\
b  & \cell{0.6}{blueB} & \cell{1}{blueB} & \cell{2.2}{redB} &
\cell{4.5}{redB} \\
c  & \cell{-2.5}{redA} & \cell{-2.5}{redA} & \cell{1.7}{blueB} &
\cell{1.2}{blueB} \\
\hline
\end{tabular}

It's a little cumbersome to tack the formatting onto an existing matrix;
the normal expectation is that a tabular() call would be used to compute
the cell values as well.

Duncan Murdoch
#
Thanks, Duncan
That's quite lovely, and makes me appreciate the tables package even more,
so I'll have to study your details.

The more general version of this idea is that rendering values in a latex
table with visual attributes (background color, font color, font family,
font shape, font weight)  according to a function of the cell value
is useful in the same way as visual attributes in plots, but, at
present, far more difficult.

best,
-Michael
On 07/23/2014 11:31 AM, Duncan Murdoch wrote: