[Tex/LaTex] Multiline table header

pgfplotstabletikz-pgf

Is it possible typeset a table with \pgfplotstabletypeset and change the style of 1 column header to be multiline?

This code doesn't work and can't compile:

...
columns/errorRelC/.style={
    column name=Line 1\\Line 2
},
...

Best Answer

An easy way to obtain this is by using the makecell package. It provides \makecell[<alignment>]{<tabular stuff>} that you can use to typeset this kind of line-breaking stuff.

\usepackage{makecell}% http://ctan.org/pkg/makecell
%...
columns/errorRelC/.style={
    column name=\makecell{Line 1\\Line 2}
},
%...

Here is a complete minimal example from the pgfplotstable package documentation:

enter image description here

\documentclass{article}
\usepackage{booktabs}% http://ctan.org/pkg/booktabs
\usepackage{pgfplotstable}% http://ctan.org/pkg/pgfplotstable
\usepackage{makecell}% http://ctan.org/pkg/makecell
\begin{document}

\pgfplotstableset{% global config, for example in the preamble
                  % these columns/<colname>/.style={<options>} things define a style
                  % which applies to <colname> only.
  columns/dof/.style={int detect,column type=r,column name=\makecell[t]{\textsc{Dof}\\Line 2}},
  columns/error1/.style={
    sci,sci zerofill,sci sep align,precision=1,sci superscript,
    column name=$e_1$,
  },
  columns/error2/.style={
    sci,sci zerofill,sci sep align,precision=2,sci 10e,
    column name=$e_2$,
  },
  columns/{grad(log(dof),log(error2))}/.style={
    string replace={0}{}, % erase '0'
    column name={$\nabla e_2$},
    dec sep align,
  },
  columns/{quot(error1)}/.style={
    string replace={0}{}, % erase '0'
    column name={$\frac{e_1^{(n)}}{e_1^{(n-1)}}$}
  },
  empty cells with={--}, % replace empty cells with '--'
  every head row/.style={before row=\toprule,after row=\midrule},
  every last row/.style={after row=\bottomrule}
  }
  \pgfplotstabletypeset[ % local config, applies only for this table
    1000 sep={\,},
    columns/info/.style={
      fixed,fixed zerofill,precision=1,showpos,
      column type=r,
    }
  ]
{
  %# Convergence results
  %# fictional source, generated 2008
  level  dof         error1         error2 info grad(log(dof),log(error2)) quot(error1)
  1        4 2.50000000e-01 7.57858283e-01 48  0              0
  2       16 6.25000000e-02 5.00000000e-01 25 -3.00000000e-01 4
  3       64 1.56250000e-02 2.87174589e-01 41 -3.99999999e-01 4
  4      256 3.90625000e-03 1.43587294e-01  8 -5.00000003e-01 4
  5     1024 9.76562500e-04 4.41941738e-02 22 -8.49999999e-01 4
  6     4096 2.44140625e-04 1.69802322e-02 46 -6.90000001e-01 4
  7    16384 6.10351562e-05 8.20091159e-03 40 -5.24999999e-01 4
  8    65536 1.52587891e-05 3.90625000e-03 48 -5.35000000e-01 3.99999999e+00
  9   262144 3.81469727e-06 1.95312500e-03 33 -5.00000000e-01 4.00000001e+00
  10 1048576 9.53674316e-07 9.76562500e-04  2 -5.00000000e-01 4.00000001e+00
}
\end{document}

I've used a top alignment in \makecell for the second column header to make the first rows of each header be vertically aligned. You can specify other alignment formats, including a different horizontal alignment. See the makecell documentation for more information.

Alternatively, you could just write the header in a tabular yourself - just like \makecell does:

\pgfplotstableset{% global config, for example in the preamble
                  % these columns/<colname>/.style={<options>} things define a style
                  % which applies to <colname> only.
  columns/dof/.style={int detect,column type=r,column name=\begin{tabular}[t]{@{}c@{}}\textsc{Dof}\\Line2\end{tabular}},
%...

Finally, you could box the content, which you then use as the column name. Here is how you would obtain an equivalent layout to the MWE above:

\newsavebox{\mybox}
\savebox{\mybox}{\begin{tabular}[t]{@{}c@{}}\textsc{Dof}\\Line2\end{tabular}}%

\pgfplotstableset{% global config, for example in the preamble
                  % these columns/<colname>/.style={<options>} things define a style
                  % which applies to <colname> only.
  columns/dof/.style={int detect,column type=r,column name=\usebox{\mybox}},
%...

The reason for all this required trickery is because the contents is inserted as-is into the table. As such, inserting \\ in the middle somewhere would terminate the row and start a new row. Therefore, you have to "contain" it to that particular cell. Using makecell allows you to do the header specification within the table and allows for more freedom if changes are required and is a clean (from a code-perspective). Inserting a tabular is a little less clean, but works just as well, while boxing is usually done "outside" of the table and used "inside" - a little more cumbersome.

In all cases, the horizontal cell padding introduced by tabular (in makecell as well) has been removed using @{}..@{}.

Related Question