43

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?

5 Answers 5

40

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}
7
  • 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, 2012 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, 2012 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, 2012 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, 2012 at 6:59
  • 4
    how do i change the code for values between 0 and 1? Oct 10, 2012 at 16:48
15

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

4
  • 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, 2016 at 9:37
  • Please embed you solution into a MWE that is actually compilable. Jul 22, 2018 at 7:10
  • 1
    @JTIM see this answer: tex.stackexchange.com/a/281828/26887 Jan 29, 2019 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, 2019 at 6:13
8

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

1
  • it is throwing an error with decimal number. my range is from 0.0 to 1 and threshold is 0.50. How can it be done then? Oct 1, 2019 at 15:08
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.

2

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .