7

I'm trying to create something like a confusion matrix of several classes. Thus, I want to display only the shades of the values.

I manage to do it using this:

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

\makeatletter
\pgfplotsset{
    /pgfplots/table/omit header/.style={%
        /pgfplots/table/typeset cell/.append code={%
            \ifnum\c@pgfplotstable@rowindex=-1
                \pgfkeyslet{/pgfplots/table/@cell content}\pgfutil@empty%
            \fi
        }
    }
}
\makeatother

\pgfplotstableset{
    color cells/.style={%
        header=false,
        omit header,
        col sep=comma,
        string type,
        postproc cell content/.code={%
                \pgfkeysalso{@cell content=\cellcolor{black!##1}\pgfmathtruncatemacro\number{##1}\ifnum\number>50\color{white}\fi}
        }
    }
}

\begin{document}
\begin{table}\caption{Correlation or something}
\centering
\pgfplotstabletypeset[color cells]{
100,0,0,0,0,0,0
0,100,0,0,0,0,0
0,0,50,0,0,0,0
0,0,1.4,90,0,0,0
0,8,0,0,95,0,8
0,5,10,0,0,60,0
0,15,0,0,0,0,80

}
\end{table}
\end{document}

However, if the number of classes increases the table won't fit in the page. Thus, I tried to reduce its size by adding font=\tiny to the color cells style. However, that produces non square cells. Moreover, I will want to tune the size of the squares to accommodate several classes that may require a size smaller than that provided by the \tiny fontsize.

\pgfplotstableset{
    color cells/.style={%
        font=\tiny,
        header=false,
        omit header,
        col sep=comma,
        string type,
        postproc cell content/.code={%
                \pgfkeysalso{@cell content=\cellcolor{black!##1}\pgfmathtruncatemacro\number{##1}\ifnum\number>50\color{white}\fi}
        }
    }
}

non-square table

Also, I'm not sure if changing the font is the correct approach to resize the cells, but I didn't find another way. If there is another way of altering the size of the cells, I will appreciate that information.

adn
  • 11,233

1 Answers1

8

After playing a little with pgfplotstable, I would use a different approach: manually draw plot with tikz, by looping through all the elements in the table. The relevant code is simple enough:

% define the sizes of the cell
\def\szx{12pt}
\def\szy{12pt}

\begin{tikzpicture}
  % loop through each column
  \pgfplotstableforeachcolumn\readtable\as\col{
    % and then for each row in the current column 
    \pgfplotstableforeachcolumnelement{\col}\of\readtable\as\colcnt{%
      \draw[draw=blue,very thin,fill=black!\colcnt]($ -\pgfplotstablerow*(0,\szy) + \col*(\szx,0) $) rectangle+(\szx,\szy);
  }
}
\end{tikzpicture}

To access the row and column indices of any element, the macros pgfplotstablerow and pgfplotstablecol are used.

The following is a complete document showing different usages. Notice that I have removed the pgfplotsset and pgfplotstableset definitions as they are no longer necessary.

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{pgfplotstable}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\pgfplotstableread[col sep=comma]{
100,0,0,0,0,0,0
0,100,0,0,0,0,0
0,0,50,0,0,0,0
0,0,1.4,90,0,0,0
0,8,0,0,95,0,8
0,5,10,0,0,60,0
0,15,0,0,0,0,80
}\readtable

Cell size: 12pt by 12pt.

\def\szx{12pt}
\def\szy{12pt}
\begin{tikzpicture}
  \pgfplotstableforeachcolumn\readtable\as\col{
    \pgfplotstableforeachcolumnelement{\col}\of\readtable\as\colcnt{%
      \draw[draw=blue,very thin,fill=black!\colcnt]($ -\pgfplotstablerow*(0,\szy) + \col*(\szx,0) $) rectangle+(\szx,\szy);
    }
  }
\end{tikzpicture}

Cell size: 4pt by 4pt.

\def\szx{4pt}
\def\szy{4pt}
\begin{tikzpicture}
  \pgfplotstableforeachcolumn\readtable\as\col{
    \pgfplotstableforeachcolumnelement{\col}\of\readtable\as\colcnt{%
      \fill[black!\colcnt]($ -\pgfplotstablerow*(0,\szy) + \col*(\szx,0) $) rectangle+(\szx,\szy);
    }
  }
\end{tikzpicture}

Cell size: 16pt by 16pt, annotated.

\def\szx{16pt}
\def\szy{16pt}
\begin{tikzpicture}
  \pgfplotstableforeachcolumn\readtable\as\col{
    \pgfplotstableforeachcolumnelement{\col}\of\readtable\as\colcnt{%
      \draw[draw=blue,very thin,fill=black!\colcnt]($ -\pgfplotstablerow*(0,\szy) + \col*(\szx,0) $) rectangle+(\szx,\szy);
      \draw[draw=blue,very thin,fill=black!\colcnt]($ -\pgfplotstablerow*(0,\szy) + 
      \col*(\szx,0) + 0.5*(\szx,\szy) $) node[font=\tiny] {\colcnt};
    }
  }
\end{tikzpicture}

\end{document}

Being drawn within a tikzpicture environment, the histograms are easier to customize.

The above document renders like this: image


EDIT

Please keep in mind that compilation times can be high using this approach.

guillem
  • 4,984