# pgfplotstable column width & row height

I am drawing a large heatmap containing only colors using \pgfplotstabletypeset. The table contains 103 columns, and 111 rows, which I am trying to squeeze in the area of 13cm * 16cm. In order to save horizontal space, I have rotated the labels in the first row by 90 degrees, but the columns are still much too wide. Simultaneously, rows are too tall.

I would like to specify table cell width and height. I'm not worried about the labels in the 1st row/column becoming super-tiny as a result of this. How do I do that?

Below, you'll find my MWE. It's inspired by this question. The only thing I found regarding the adjustment of column widths in pgfplotstable can be found in Sec. 2.3 of the pgfplotstablr docs. I already applied that in my MWE, but it doesn't do much in my favor.

\documentclass{standalone}

\listfiles
\usepackage{colortbl}
\usepackage{array}
\usepackage{filecontents}
\usepackage{pgfplotstable}
\usetikzlibrary{pgfplots.colormaps}

\pgfplotsset{compat=1.9}
\pgfplotsset{
colormap={myCustomColorMap}{
color(0)=(blue);
color(1)=(red);
},
}

% https://tex.stackexchange.com/a/158985/31877
\pgfplotstableset{
/color cells/min/.initial=0,
/color cells/max/.initial=1000,
/color cells/textcolor/.initial=,
/color cells/colormap name/.initial=,% this was added
%
% Usage: 'color cells={min=<value which is mapped to lowest color>,
%   max = <value which is mapped to largest>}
color cells/.code={%
\pgfqkeys{/color cells}{#1}%
\pgfkeysalso{%
postproc cell content/.code={%
\begingroup
% acquire the value before any number printer changed it:
\pgfkeysgetvalue{/pgfplots/table/@preprocessed cell content}\value
\ifx\value\empty
\endgroup
\else
\pgfkeys{/pgf/fpu=true}%
\pgfmathparse{log10(\value)}%
\pgfmathfloattofixed{\pgfmathresult}%
\let\value=\pgfmathresult
\pgfkeys{/pgf/fpu=false}%
% map that value:
\pgfplotscolormapaccess
[\pgfkeysvalueof{/color cells/min}:\pgfkeysvalueof{/color cells/max}]
{\value}
{\pgfkeysvalueof{/color cells/colormap name}}% I CHANGED THIS
% now, \pgfmathresult contains {<R>,<G>,<B>}
%
% acquire the value AFTER any preprocessor or
% typesetter (like number printer) worked on it:
\pgfkeysgetvalue{/pgfplots/table/@cell content}\typesetvalue
\pgfkeysgetvalue{/color cells/textcolor}\textcolorvalue
% tex-expansion control
\toks0=\expandafter{\empty}%\typesetvalue}%
\xdef\temp{%
\noexpand\pgfkeysalso{%
@cell content={%
\noexpand\cellcolor[rgb]{\pgfmathresult}%
\noexpand\definecolor{mapped color}{rgb}{\pgfmathresult}%
\ifx\textcolorvalue\empty
\else
\noexpand\color{\textcolorvalue}%
\fi
\the\toks0 %
}%
}%
}%
\endgroup
\temp
\fi
}%
}%
}
}

\pgfmathdeclarefunction{lg10}{1}{%
\pgfmathparse{ln(#1)/ln(10)}%
}

\begin{filecontents}{data.csv}
item,Xa,Xb,Ya,Yb,Za,Zb
a,2,,2,,783764,783764
b,,2,,,500000,500000
c,,5,,,100000,100000
d,2,,8,,20000,20000
e,,,,,10000,10000
f,,,,3,5000,5000
g,,2,,,1000,1000
h,6,,,4,500,500
i,,,4,,100,100
j,,,,,50,50
k,,2,,,10,10
l,,,7,,5,5
m,,6,,3,2,2
n,,,,,1,1
\end{filecontents}

\begin{document}
\newcolumntype{C}{>{\centering\arraybackslash}p{1mm}}

\pgfplotstabletypeset[
font=\tiny,
typeset cell/.code={
\ifnum\pgfplotstablecol=1
\pgfkeyssetvalue{/pgfplots/table/@cell content}{&}%
\else
\ifnum\pgfplotstablecol=\pgfplotstablecols
\pgfkeyssetvalue{/pgfplots/table/@cell content}{\rotatebox{90}{##1}\\}%
\else
\pgfkeyssetvalue{/pgfplots/table/@cell content}{\rotatebox{90}{##1}&}%
\fi
\fi
}
},
%max=lg10(783764)
colorCell/.style={
column type=C,
color cells={min=0,max=5.9,colormap name=myCustomColorMap}
},
itemCell/.style={
string type,
column name={},
},
col sep=comma,
columns={item,Xa,Xb,Ya,Yb,Za,Zb},
columns/item/.style={itemCell},
columns/Xa/.style={colorCell},
columns/Xb/.style={colorCell},
columns/Ya/.style={colorCell},
columns/Yb/.style={colorCell},
columns/Za/.style={colorCell},
columns/Zb/.style={colorCell},
]{data.csv}

\end{document}


The easiest solution may be to put the pgfplotstable into the \resizebox command. From Wikibooks:

The graphicx packages features the command \resizebox{width}{height}{object} which can be used with tabular to specify the height and width of a table.

\documentclass{standalone}

\listfiles
\usepackage{colortbl}
\usepackage{array}
\usepackage{filecontents}
\usepackage{pgfplotstable}
\usepackage{graphicx}
\usetikzlibrary{pgfplots.colormaps}

\pgfplotsset{compat=1.9}
\pgfplotsset{
colormap={myCustomColorMap}{
color(0)=(blue);
color(1)=(red);
},
}

% http://tex.stackexchange.com/a/158985/31877
\pgfplotstableset{
/color cells/min/.initial=0,
/color cells/max/.initial=1000,
/color cells/textcolor/.initial=,
/color cells/colormap name/.initial=,% this was added
%
% Usage: 'color cells={min=<value which is mapped to lowest color>,
%   max = <value which is mapped to largest>}
color cells/.code={%
\pgfqkeys{/color cells}{#1}%
\pgfkeysalso{%
postproc cell content/.code={%
\begingroup
% acquire the value before any number printer changed it:
\pgfkeysgetvalue{/pgfplots/table/@preprocessed cell content}\value
\ifx\value\empty
\endgroup
\else
\pgfkeys{/pgf/fpu=true}%
\pgfmathparse{log10(\value)}%
\pgfmathfloattofixed{\pgfmathresult}%
\let\value=\pgfmathresult
\pgfkeys{/pgf/fpu=false}%
% map that value:
\pgfplotscolormapaccess
[\pgfkeysvalueof{/color cells/min}:\pgfkeysvalueof{/color cells/max}]
{\value}
{\pgfkeysvalueof{/color cells/colormap name}}% I CHANGED THIS
% now, \pgfmathresult contains {<R>,<G>,<B>}
%
% acquire the value AFTER any preprocessor or
% typesetter (like number printer) worked on it:
\pgfkeysgetvalue{/pgfplots/table/@cell content}\typesetvalue
\pgfkeysgetvalue{/color cells/textcolor}\textcolorvalue
% tex-expansion control
\toks0=\expandafter{\empty}%\typesetvalue}%
\xdef\temp{%
\noexpand\pgfkeysalso{%
@cell content={%
\noexpand\cellcolor[rgb]{\pgfmathresult}%
\noexpand\definecolor{mapped color}{rgb}{\pgfmathresult}%
\ifx\textcolorvalue\empty
\else
\noexpand\color{\textcolorvalue}%
\fi
\the\toks0 %
}%
}%
}%
\endgroup
\temp
\fi
}%
}%
}
}

\pgfmathdeclarefunction{lg10}{1}{%
\pgfmathparse{ln(#1)/ln(10)}%
}

\begin{filecontents}{data.csv}
item,Xa,Xb,Ya,Yb,Za,Zb
a,2,,2,,783764,783764
b,,2,,,500000,500000
c,,5,,,100000,100000
d,2,,8,,20000,20000
e,,,,,10000,10000
f,,,,3,5000,5000
g,,2,,,1000,1000
h,6,,,4,500,500
i,,,4,,100,100
j,,,,,50,50
k,,2,,,10,10
l,,,7,,5,5
m,,6,,3,2,2
n,,,,,1,1
\end{filecontents}

\newcolumntype{C}{>{\centering\arraybackslash}p{1mm}}

\begin{document}
\resizebox{3in}{2in}{\pgfplotstabletypeset[
font=\tiny,
typeset cell/.code={
\ifnum\pgfplotstablecol=1
\pgfkeyssetvalue{/pgfplots/table/@cell content}{&}%
\else
\ifnum\pgfplotstablecol=\pgfplotstablecols
\pgfkeyssetvalue{/pgfplots/table/@cell content}{\rotatebox{90}{##1}\\}%
\else
\pgfkeyssetvalue{/pgfplots/table/@cell content}{\rotatebox{90}{##1}&}%
\fi
\fi
}
},
%max=lg10(783764)
colorCell/.style={
column type=C,
color cells={min=0,max=5.9,colormap name=myCustomColorMap}
},
itemCell/.style={
string type,
column name={},
},
col sep=comma,
columns={item,Xa,Xb,Ya,Yb,Za,Zb},
columns/item/.style={itemCell},
columns/Xa/.style={colorCell},
columns/Xb/.style={colorCell},
columns/Ya/.style={colorCell},
columns/Yb/.style={colorCell},
columns/Za/.style={colorCell},
columns/Zb/.style={colorCell},
]{data.csv}}
\end{document}


One strange thing about this though is that even though I specify the options width=3in and height=2in to \resizebox, for some reason my output has width 3.01 in and height 3.9 in. I don't know why \resizebox gets the height wrong by a multiplicative factor.

• I was considering that. But I'm a bit reluctant, since this destroys the aesthetically pleasing proportions of the font used; Even if the text becomes insanely tiny. – derabbink Feb 7 '14 at 18:22

Based on what I learned in How to map value to color using TikZ?, I am able to do what you want by using the R programming language to pre-process the input file, then to draw each rectangle using TikZ and a \foreach loop. (The answer in Need some help getting started with TikZ, groupplots and color mapping of matrix uses a similar approach where instead of using pgfplotstable, the answerer draws his own "table" using TikZ). Unfortunately I don't know enough TeX to do all the processing in TeX, so I did the processing in R. (But you could use your favorite programming language instead of R).

First, I save the input file as a text file 2014-02-09.txt.

Next, I run an R script to compute the base-10 logs, and output the entries in the input file into a LaTeX list. (Note: R is a widely used statistical programming language.)

temp <- read.table('2014-02-09.txt', sep=',', header = TRUE)

sink('2014-02-09-converted.tex')
prestring <- ''
cat('\\newcommand*{\\ListOfRectangles}{')
cat('%x/y/value\n')
for (i in 1:nrow(temp)) {
for (j in 2:ncol(temp)) {
value <- log(temp[i,j]) / log(10)
if (!is.na(value)) {
cat(sprintf('%s%d/%d/%.2f', prestring, j, i, value))
prestring <- ',\n'
}
}
}
cat('%\n}')
sink()


The output is a file 2014-02-09-converted.tex whose contents are:

\newcommand*{\ListOfRectangles}{%x/y/value
2/1/0.30,
4/1/0.30,
6/1/5.89,
7/1/5.89,
3/2/0.30,
6/2/5.70,
7/2/5.70,
3/3/0.70,
6/3/5.00,
7/3/5.00,
2/4/0.30,
4/4/0.90,
6/4/4.30,
7/4/4.30,
6/5/4.00,
7/5/4.00,
5/6/0.48,
6/6/3.70,
7/6/3.70,
3/7/0.30,
6/7/3.00,
7/7/3.00,
2/8/0.78,
5/8/0.60,
6/8/2.70,
7/8/2.70,
4/9/0.60,
6/9/2.00,
7/9/2.00,
6/10/1.70,
7/10/1.70,
3/11/0.30,
6/11/1.00,
7/11/1.00,
4/12/0.85,
6/12/0.70,
7/12/0.70,
3/13/0.78,
5/13/0.48,
6/13/0.30,
7/13/0.30,
6/14/0.00,
7/14/0.00%
}


Finally, I compile the LaTeX code which \inputs the previously computed list. Notice that by varying the xscale and yscale options you can change the size of the PDF output.

\documentclass{standalone}

\usepackage{tikz}

\input{2014-02-09-converted}

\begin{document}
% to change the output size of the PDF, change the xscale and yscale values.
\begin{tikzpicture}[xscale=0.5,yscale=0.3]
\colorlet{color min}[rgb]{blue}
\colorlet{color max}[rgb]{red}

\def\min{0}
\def\max{5.89}

\foreach \sX/\sY/\myvalue in \ListOfRectangles {
\pgfmathtruncatemacro\lambda{(\max-\myvalue)/(\max-\min)*100}
\colorlet{my color}[rgb]{color min!\lambda!color max}
\fill[my color] (\sX, -\sY) rectangle +(1cm,1cm);
}
\end{tikzpicture}
\end{document}


Output: