2

I want to gernerate a cross table with booktabs. Therfore, I have 2 data sets I want to compare to each other.

The table should look like the pic below but I do not get it to write the vertical header properly. Maybe somebody can help?

enter image description here

I want to get a rotated header from row 8 to row 2 with a line break before "Data2". And if possible, another vertical cmidrule would be nice.

Here is a MWE :) Thanks a lot!

\documentclass[a4paper, 12pt, headsepline]{scrreprt}
\usepackage[utf8]{inputenc}

\usepackage{booktabs}
\usepackage{multirow}
\usepackage{rotating}
\usepackage{makecell}
\renewcommand\theadfont{\bfseries}

\begin{document}

\begin{table}[!h]
  \centering
  \begin{tabular}{cccccccc}
    \toprule
    & & \multicolumn{6}{c}{\thead{Long text for Data1}} \\
    \cmidrule(lr){3-8}
    & & \thead{0} & \thead{1} & \thead{2} & \thead{3} & \thead{5} & \thead{10}\\
    \midrule
    \multirowcell{6}[0pt]{\rothead{Long text for\\Data2}}& \thead{0} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{1} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{2} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{3} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{5} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{10} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}
Max16hr
  • 503

3 Answers3

2

Use a \raisebox and a \rotatebox in the last row, first cell. The heading is type set in a \parbox inside the \rotatebox:

Example 1 – raisebox, rotatebox and parbox

enter image description here

\documentclass[a4paper, 12pt, headsepline]{scrreprt}
\usepackage[utf8]{inputenc}

\usepackage{booktabs}
\usepackage{multirow}
\usepackage{rotating}
\usepackage{makecell}
\renewcommand\theadfont{\bfseries}

\begin{document}

\begin{table}[!h]
  \centering
  \begin{tabular}{p{1cm}>{\bfseries}ccccccc}
    \toprule
    & & \multicolumn{6}{c}{\thead{Long text for Data1}} \\
    \cmidrule(lr){3-8}
    & & \thead{0} & \thead{1} & \thead{2} & \thead{3} & \thead{5} & \thead{10}\\
    \midrule
    & 0 & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & 1 & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & 2 & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & 3 & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & 5 & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
\raisebox{35pt}[0pt][0pt]{\rotatebox[origin=c]{90}{\parbox{2.5cm}{\centering Long text for \\ Data2}}}    & 10 & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}

Example 2 – raisebox, rotatebox and nested tabular

Another possible solution is using nested tabular inside the \rotatebox. The tabular is type set by defining a new command, \tstack. The vertical rule is a \cmidrule that is fined tuned to extend until it meet the horizontal rules. The per cent sign (%) I have moved from cell/column to heading. You may consider to reduce the font size in the headings to footnotesize to make them less dominant.

enter image description here

\documentclass[a4paper, 12pt, headsepline]{scrreprt}
\usepackage[utf8]{inputenc}
\usepackage{booktabs, array}
\usepackage{rotating}
\usepackage{makecell}
\renewcommand\theadfont{\bfseries}

% Multi-line left-aligned text with manual line breaks.
% The base line of the whole is at the top row.
\newcommand*{\tstack}[1]{%
  \begingroup
    \renewcommand*{\arraystretch}{1}%
    \begin{tabular}[t]{@{}>{\bfseries}c@{}}#1\\\cmidrule(l{-0.65em}r{-0.65em}){1-1} \end{tabular}%
  \endgroup
}

\begin{document}

\begin{table}[!h]
  \centering
  \begin{tabular}{@{}>{\centering\arraybackslash}p{1cm}>{\bfseries}rcccccc}
    \toprule
    & & \multicolumn{6}{c}{\thead{Long text for Data1}} \\
    \cmidrule(lr){3-8}
    & & \thead{0 (\%)}  & \thead{1 (\%)} & \thead{2 (\%)} & \thead{3 (\%)} & \thead{5 (\%)} & \thead{10 (\%)}\\
    \midrule
    & 0 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 1 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 2 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 3 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 5 & ??? & ??? & ??? & ??? & ??? & ??? \\
\raisebox{47pt}[0pt][0pt]{\rotatebox[origin=c]{90}{\tstack{Long text for \\ Data2}}}    & 10 & ??? & ??? & ??? & ??? & ??? & ??? \\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}

Example 3 – nested tabular and vertical rule

enter image description here

If you accept small gaps between the vertical rule in column 1 and the horizontal rules (which I think s OK in this tabular), a more automatic solution is to use an ordinary rule (|) between column 1 and column 2, which you cancel with a multicolumn in row 1 and row. In the example below I have also reduced the font size, which is more pleasant when you use bold.

\documentclass[a4paper, 12pt, headsepline]{scrreprt}
\usepackage[utf8]{inputenc}
\usepackage{booktabs, array}
\usepackage{rotating}
\usepackage{makecell}
\renewcommand\theadfont{\bfseries\footnotesize}

% Multi-line left-aligned text with manual line breaks.
% The base line of the whole is at the top row.
\newcommand*{\tstack}[1]{%
  \begingroup
    \renewcommand*{\arraystretch}{1}%
    \begin{tabular}[t]{@{}c@{}}#1\end{tabular}%
  \endgroup
}

\begin{document}
\begin{table}[!h]
  \centering
  \begin{tabular}{@{}>{\footnotesize\bfseries\centering\arraybackslash}p{1.1cm}|>{\bfseries}rcccccc@{}}
    \toprule
\multicolumn{1}{c}{}       & & \multicolumn{6}{c}{\thead{Long text for Data1}} \\
    \cmidrule(l){3-8}
\multicolumn{1}{c}{}       & & \thead{0\,(\%)}  & \thead{1\,(\%)} & \thead{2\,(\%)} & \thead{3\,(\%)} & \thead{5\,(\%)} & \thead{10\,(\%)}\\
    \midrule
    & 0 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 1 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 2 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 3 & ??? & ??? & ??? & ??? & ??? & ??? \\
    & 5 & ??? & ??? & ??? & ??? & ??? & ??? \\
\raisebox{44pt}[0pt][0pt]{\rotatebox[origin=c]{90}{\tstack{Long text for \\ Data2}}}    & 10 & ??? & ??? & ??? & ??? & ??? & ??? \\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}
Sveinung
  • 20,355
2

A solution with only \thead, cheating with the number of rows in \multirow:

\documentclass[a4paper, 12pt, headsepline]{scrreprt}
\usepackage[utf8]{inputenc}

\usepackage{booktabs}
\usepackage{multirow}
\usepackage{rotating}
\usepackage{makecell}
\renewcommand\theadfont{\bfseries}

\begin{document}

\begin{table}[!h]
  \centering
\settowidth\rotheadsize{\theadfont Long text for}
   \begin{tabular}{cccccccc}
    \toprule
    & & \multicolumn{6}{c}{\thead{Long text for Data1}} \\
    \cmidrule(lr){3-8}
    & & \thead{0} & \thead{1} & \thead{2} & \thead{3} & \thead{5} & \thead{10}\\
    \midrule
  \multirow{8}{*}{\rotatebox[origin=c]{90}{\thead{Long text for\\ Data2}}} & \thead{0} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{1} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{2} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{3} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{5} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    & \thead{10} & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% & ???\,\% \\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}

enter image description here

Bernard
  • 271,350
  • Since you define size of \rothead I expect that instead of \multirow{8}{*}{\rotatebox[origin=c]{90}{\thead{Long text for\\ Data2}}} you will write \multirow{8}{*}{\rothead{\centering Long text for\\ Data2}} :-) – Zarko Jan 21 '20 at 01:36
  • @Zarko: That's one of the things I tried first, but the (horizontal) placement f the vertical text wasn't what I expected. Yet I needed o define size of the text to make the code work correctly. – Bernard Jan 21 '20 at 10:13
  • Using @Allan Munn patch \makeatletter \def\@rothead[#1]#2{\thead{\\[-.65\normalbaselineskip] \turn{\cellrotangle}\thead[#1]{#2}\endturn}} \makeatother (see https://tex.stackexchange.com/questions/8149/) in preamble and than \multirow{8}{*}{\rothead[c]{Long text for\\ Data2}} gives the same result as your approach. Of course, your solution works very wel :-) – Zarko Jan 21 '20 at 10:46
  • @Zarko: I didn't know this patch, thanks for the information! It's been quite some time that I've noticed problems with \rothead/cell except in very simple cases, but the package doesn't seem to be maintained, just like floatrow from the same author. – Bernard Jan 21 '20 at 11:26
  • You are right about maintaining, and this is pity. Beside mention patch also exist patch for use of m column type (from @Ulrike Fischer, https://tex.stackexchange.com/questions/319768/). I would be very glad, if some make fix of the makecell package with this two patch (for example similarly as was partly done for the tabu package). Unfortunately I'm not skilled for such job :-( – Zarko Jan 21 '20 at 11:49
1

Here is a solution with {NiceTabular} of nicematrix. This environment is similar with {tabular} (of array) but provides some other functionnalies.

In {NiceTabular}, you merge cells both horizontally and vertically with the command \Block. For the rows, you give the number of logical rows (and not the number of physical lines as with \multicolumn).

A built-in command \rotate is provided to rotate the content of the block.

\documentclass[a4paper, 12pt, headsepline]{scrreprt}

\usepackage{booktabs} \usepackage{nicematrix}

\begin{document}

\begin{table}[!h] \centering \begin{NiceTabular}{>{\bfseries}c>{\bfseries}ccccccc}[cell-space-limits=3pt] \toprule \RowStyle[nb-rows=2]{\bfseries} & & \Block{1-6}{Long text for Data1} \ \cmidrule(lr){3-8} & & 0 & 1 & 2 & 3 & 5 & 10 \ \midrule \Block{6-1}<\rotate>{Long text for\ Data2} & 0 & ???,% & ???,% & ???,% & ???,% & ???,% & ???,% \ & 1 & ???,% & ???,% & ???,% & ???,% & ???,% & ???,% \ & 2 & ???,% & ???,% & ???,% & ???,% & ???,% & ???,% \ & 3 & ???,% & ???,% & ???,% & ???,% & ???,% & ???,% \ & 5 & ???,% & ???,% & ???,% & ???,% & ???,% & ???,% \ & 10 & ???,% & ???,% & ???,% & ???,% & ???,% & ???,% \ \bottomrule \end{NiceTabular} \end{table}

\end{document}

You need several compilations (because nicematrix uses PGF/Tikz nodes under the hood).

Output of the above code

F. Pantigny
  • 40,250