38

I wanted to do some shading in a table according to its values. For example, if you see the table below:

  a  b   c   d 
a 90 10  0   0
b 0  80  10  10
c 0  0   95  5
d 0  10  5   85

I want to shade automatically each numeric cell with a mixture of black and white according to its value. That is, (a,a) = 90 should be something like black!90, and (c,d) = 5 should be black!5. Also, if you can parametrized the shading operation so one can define the color and if we use the value or the complement that would be great.

I was thinking in something like Drawing different tikz shapes parameterized by data from a file, but I cannot see how can one achieve that in a table.

Can you give me some advice on how to achieve such automatic styling?

37

You could use pgfplotstable and the xcolor package with the [table] option, which gives you the \cellcolor command.

Here's a new style for \pgfplotstabletypeset that colors the cell a different shade of gray according to the cell value, and prints the value in white if the background is more than 50% black.

The command

\pgfplotstabletypeset[color cells]{
 x,a,b,c,d      % The first column needs a name
 a,90,10,0,0
 b,0,80,10,10
 c,0,0,95,5
 d,0,10,5,85
 }

will then give you (shown here with a caption)

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{pgfplotstable}

\pgfplotstableset{
    color cells/.style={
        col sep=comma,
        string type,
        postproc cell content/.code={%
                \pgfkeysalso{@cell content=\rule{0cm}{2.4ex}\cellcolor{black!##1}\pgfmathtruncatemacro\number{##1}\ifnum\number>50\color{white}\fi##1}%
                },
        columns/x/.style={
            column name={},
            postproc cell content/.code={}
        }
    }
}

\begin{document}
\begin{table}\caption{Correlation or something}
\centering
\pgfplotstabletypeset[color cells]{
x,a,b,c,d
a,90,10.5,0,0
b,0,80,10,10
c,0,0,95,5
d,0,10,5,85
}
\end{table}
\end{document}
  • Thanks it works really nice. That was what I was expecting. However, when I put the \pgfplotstabletypeset inside a table environment (\begin{table} ... \end{table}) I get a Not in outer par mode error. So, is there any option to put that table in an environment? so I can add a caption to it, and style as other tables in my document? – adn Jan 27 '12 at 6:25
  • That error occurs only if you're using the standalone class. In "normal" classes, you should be able to use the table environment. I've edited my example. – Jake Jan 27 '12 at 6:35
  • 1
    Don't worry, I was quite surprised that it didn't work in standalone, too. The numbers look like they're too far up because there's space left for the descender of letters like g, j, or q. If you add \rule{0cm}{2.4ex} before \cellcolor, they'll loke more centered. – Jake Jan 27 '12 at 6:49
  • 1
    \pgfmathtruncatemacro\somemacroname{##1}. You need to save the result into a macro, the command doesn't change the content of ##1 itself. – Jake Jan 27 '12 at 6:59
  • 2
    how do i change the code for values between 0 and 1? – jstr Oct 10 '12 at 16:48
11

I wanted to retain the use of tabular, so I used a macro to format the cells. Definitely longer but more familiar to me.

\def\cca#1{\cellcolor{black!#10}\ifnum #1>5\color{white}\fi{#1}}
%For ranges 0-10, multiply by 10 by adding 0 after #1

\begin{table}[!t]
\caption{Table Caption}
\label{tab1}
\centering
{\setlength\tabcolsep{0.1pt}%
\begin{tabular}{ccccccccccccccc}
& $D_1$ & $D_2$ & $D_3$ & $D_4$ & $D_5$ & $D_6$ && & $D_1$ & $D_2$ & $D_3$ & $D_4$ & $D_5$ & $D_6$ \\
$D_1$ & & \cca{0} & \cca{0} & \cca{0} & \cca{2} & \cca{0} && $D_1$ && \cca{0} & \cca{0} & \cca{2} & \cca{2} & \cca{2} \\
$D_2$ & \cca{0} & & \cca{2} & \cca{0} & \cca{2} & \cca{0} && $D_2$ & \cca{0} &  & \cca{3} & \cca{0} & \cca{0} & \cca{2} \\
$D_3$ & \cca{7} & \cca{4} &  & \cca{3} & \cca{0} & \cca{4} && $D_3$ & \cca{0} & \cca{4} &  & \cca{4} & \cca{2} & \cca{0} \\
$D_4$ & \cca{3} & \cca{0} & \cca{7} &  & \cca{4} & \cca{0} && $D_4$ & \cca{0} & \cca{0} & \cca{5} &  & \cca{0} & \cca{0} \\
$D_5$ & \cca{3} & \cca{7} & \cca{7} & \cca{2} &  & \cca{4} && $D_5$ & \cca{2} & \cca{2} & \cca{0} & \cca{4} &  & \cca{4} \\
$D_6$ & \cca{2} & \cca{2} & \cca{7} & \cca{2} & \cca{6} &  && $D_6$ & \cca{2} & \cca{2} & \cca{3} & \cca{0} & \cca{4} & \\
\end{tabular}}
\end{table}

table result

  • this looks like exactly what I need. But I get errors when I try to change the range. If I wanted something like 0-230, how would I amend your \def? Hope you can help :) – JTIM Feb 15 '16 at 9:37
  • Please embed you solution into a MWE that is actually compilable. – Christoph90 Jul 22 '18 at 7:10
  • 1
    @JTIM see this answer: tex.stackexchange.com/a/281828/26887 – Daniel Hershcovich Jan 29 at 14:33
  • @DanielHershcovich Cool to give such a comment, I ended up solving it in a different way back then :) But THX! – JTIM Jan 30 at 6:13
4

If you want that the cell background color changes according to its values.

Correlation or other kind of matrix

You can use the following code.

\documentclass[english]{article}
\usepackage[T1]{fontenc}
\usepackage[latin9]{inputenc}
\usepackage{babel}
\usepackage[table]{xcolor}
\usepackage{collcell}
\usepackage{hhline}
\usepackage{pgf}
\usepackage{multirow}

\def\colorModel{hsb} %You can use rgb or hsb

\newcommand\ColCell[1]{
  \pgfmathparse{#1<50?1:0}  %Threshold for changing the font color into the cells
    \ifnum\pgfmathresult=0\relax\color{white}\fi
  \pgfmathsetmacro\compA{0}      %Component R or H
  \pgfmathsetmacro\compB{#1/100} %Component G or S
  \pgfmathsetmacro\compC{1}      %Component B or B
  \edef\x{\noexpand\centering\noexpand\cellcolor[\colorModel]{\compA,\compB,\compC}}\x #1
  } 
\newcolumntype{E}{>{\collectcell\ColCell}m{0.4cm}<{\endcollectcell}}  %Cell width

\begin{document}
\newcommand\items{3}   %Number of classes
\arrayrulecolor{white} %Table line colors
\noindent\begin{tabular}{c*{\items}{|E}|}
\multicolumn{1}{c}{} & 
\multicolumn{1}{c}{A} & 
\multicolumn{1}{c}{B} & 
\multicolumn{1}{c}{C} \\ \hhline{~*\items{|-}|}
A  & 100   & 0  & 10   \\ \hhline{~*\items{|-}|}
B  & 10   & 80  & 10   \\ \hhline{~*\items{|-}|}
C  & 30   & 0   & 70   \\ \hhline{~*\items{|-}|}
\end{tabular}

\end{document}

You can use RGB or HSB to define your color ranges, and you can control de color ranges using the formulas in compA, compB and compC.

So, for "Autum" (red-yellow) range use:

\pgfmathsetmacro\compA{#1/600} %Component R or H
\pgfmathsetmacro\compB{1} %Component G or S
\pgfmathsetmacro\compC{1} %Component B or B

And, for "Cool" (cyan-magenta) range set rgb for color model and use:

\pgfmathsetmacro\compA{#1/100}   %Component R or H
\pgfmathsetmacro\compB{1-#1/100} %Component G or S
\pgfmathsetmacro\compC{1}        %Component B or B

For "Black-red" range use:

\pgfmathsetmacro\compA{0} %Component R or H
\pgfmathsetmacro\compB{1} %Component G or S
\pgfmathsetmacro\compC{#1/100} %Component B or B

For "Jet" range use:

\pgfmathsetmacro\compA{0.6666-#1/150}      %Component R or H
\pgfmathsetmacro\compB{1} %Component G or S
\pgfmathsetmacro\compC{1}      %Component B or B

For "Cooper" range use:

\pgfmathsetmacro\compA{0.08+#1/5000}      %Component R or H
\pgfmathsetmacro\compB{0.7} %Component G or S
\pgfmathsetmacro\compC{#1/100}      %Component B or B

For "Gray" range use:

\pgfmathsetmacro\compA{0}      %Component R or H
\pgfmathsetmacro\compB{0} %Component G or S
\pgfmathsetmacro\compC{#1/100}      %Component B or B

enter image description here

2
\definecolor{myFlowTableTextCol}{rgb}{0,0,0}
\definecolor{myFlowTableBgCol}{rgb}{1.0,0.5,0.0}

% Heatmap style
\pgfkeys{
/pgfplots/table/heatmap/.style =
{
header=false,
column type={p{0.4cm}},
display columns/0/.style={column name=$\phantom{x}$},
display columns/1/.style={column name=$\phantom{x}$},
display columns/2/.style={column name=$\phantom{x}$},
display columns/3/.style={column name=$\phantom{x}$},
display columns/4/.style={column name=$\phantom{x}$},
display columns/5/.style={column name=$\phantom{x}$},
display columns/6/.style={column name=$\phantom{x}$},
display columns/7/.style={column name=$\phantom{x}$},
display columns/8/.style={column name=$\phantom{x}$},
display columns/9/.style={column name=$\phantom{x}$},
display columns/10/.style={column name=$\phantom{x}$},
postproc cell content/.code=
{%
\pgfkeysalso{/pgfplots/table/@cell content=\pgfmathparse{#1} \edef\multFact{\pgfmathresult} \pgfmathparse{round(##1*\multFact)} \edef\x{\pgfmathresult} \pgfmathtruncatemacro{\y}{\x}

\rule{0cm}{2.4ex}%\y,\y,\y}
\ifnum\y<0 \color{lightgray}\cellcolor{lightgray}\fi
\ifnum\y>0 \ifnum\y <6 \color{myFlowTableTextCol}\cellcolor{myFlowTableBgCol!36}\fi\fi
...
\y
},
},
/pgfplots/table/heatmap/.default=100
}

...
\pgfplotstabletypeset[heatmap=162]{data.dat}

even allows you to preprocess (multiply in this case) the data before colouring the heatmap. Especially for pgf versions < 1.5 this can be hard otherwise.

0

I used @Unas answer with the following twist for a custom range, 93.6 to 97.2 in this case:

\def\cca#1{%
    \pgfmathsetmacro\calc{(#1-93.6)*100/(97.2-93.6)}%
    \edef\clrmacro{\noexpand\cellcolor{blue!\calc}}%
    \clrmacro%
    \ifdim \calc pt>50pt\color{white}\fi{#1}%
}

The reason for the \edef instead of simply having \cellcolor{blue!\calc} is that otherwise the \calc part does not expand.

Also note the % at the end of each line. This prevents spaces from appearing in the cells

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.