# How can I auto-equalize the width of columns whose contents are similar?

Assume that we have a table and we want LaTeX to automatically determine its columns' width provided that column widths are equal. Such a problem can be solved by defining a new column type as follows: \newcolumntype{C}{ >{ \arraybackslash \Centering } X }. However, when using such command, LaTeX will make column widths equal, but this may result in suboptimal output like this:

Which is generated using the following code:

\documentclass{report}

\usepackage{amsmath}
\usepackage{amssymb, amsfonts}
\usepackage[flushleft]{threeparttable}
\usepackage{makecell}

\usepackage{ragged2e}
\usepackage{tabularx}
\newcolumntype{L}{ >{ \arraybackslash \RaggedRight } X } % left justified
\newcolumntype{C}{ >{ \arraybackslash \Centering } X } % centered
\newcolumntype{R}{ >{ \arraybackslash \RaggedLeft } X } % right justified
\newcolumntype{J}{ >{ \arraybackslash \justifying } X } % justified
\renewcommand \tabularxcolumn [1] { >{ \centering } m{#1} }
\usepackage{booktabs}
\newcolumntype{A}[1]{ >{ \arraybackslash \RaggedRight } m{#1} }
\newcolumntype{S}[1]{ >{ \arraybackslash \Centering } m{#1} }
\newcolumntype{D}[1]{ >{ \arraybackslash \RaggedLeft } m{#1} }
\newcolumntype{F}[1]{ >{ \arraybackslash \justifying } m{#1} }
\usepackage{multirow}

\begin{document}

\begin{table*}[]

% Table options
\caption{Elasticity Values}
\label{table:PV_mod_STC_comp2}

% Center the table
\centering

% Stretch the table (vertically)
\renewcommand{\arraystretch}{1.3}

\toprule

\multirow{2}{*}{
\textbf{Customer type}
} &
\multicolumn{2}{c}{
\multirow{2}{*}{\textbf{Set 1}}
}
&
\multicolumn{2}{|c}{
\multirow{2}{*}{\textbf{Set 2}}
}
\\

\multicolumn{1}{c|}{} &
\multicolumn{2}{c}{} &
\multicolumn{2}{|c}{}
\\
\Xhline{0.2 mm}

\textbf{Residential} &
$-0.09$ to $-0.5$ &
$-0.12$ to $-1.56$ & $1$ & $2$
\\
\Xhline{0.2 mm}

\textbf{Commercial} & $-0.019$ to $-0.25$ & $-0.44$ to $-0.97$ & $3$ & $4$
\\
\Xhline{0.2 mm}

\textbf{Industrial} & $-0.005$ to $-0.14$ & $-0.34$ to $-5.48$ & $5$ &
$6$
\\

\bottomrule

\end{tabularx}

\end{table*}

\end{document}


An optimized code should result in something like this:

Which is generated by replacing the last two columns with a constant width of 1cm each. However, I want LaTeX to automatically make the last two columns small (because their contents are small) while forcing both columns to be equal. In other words, I want to define a new column type, say its name is NewCol, and use it in the table command \begin{tabularx}{1\textwidth}{ D{2.6cm}@{\quad} |C|C| NewCol|NewCol }. NewCol here should result in columns of equal widths but different in size from the column type C. The widths of both NewCol and C should be aumatically determined according to the contents of columns and the allowable length defined in the syntax.

This solution measures the combined columns, then uses those widths for the tabular. The drawback is that you have to enter the data twice. Note that the title of Set 2 is wider than the data.

I made a number of gratuitous changes, mostly to simplify the code.

\documentclass{report}

\usepackage{amsmath}
\usepackage{amssymb, amsfonts}
\usepackage[flushleft]{threeparttable}
\usepackage{makecell}
\usepackage{ragged2e}
\usepackage{multirow}
% none of the above are used here

\usepackage{booktabs}
\newcolumntype{C}[1]{ >{\hfil} m{#1} }
\newcolumntype{D}[1]{ >{\hfill} m{#1} }
\newcommand{\bigstrut}{\rule[\dimexpr -\arraystretch\dp\strutbox-1ex]{0pt}{0pt}%
\rule{0pt}{\dimexpr \arraystretch\ht\strutbox+1ex}}

\begin{document}

\begin{table*}[]
\sbox0{\begin{tabular}{@{}l@{}}% measure set 1
$-0.09$ to $-0.5$\\
$-0.12$ to $-1.56$\\
$-0.019$ to $-0.25$\\
$-0.44$ to $-0.97$\\
$-0.005$ to $-0.14$\\
$-0.34$ to $-5.48$
\end{tabular}}
\sbox1{\begin{tabular}{@{}l@{}}% measure set 2
1\\
2\\
3\\
4\\
5\\
6
\end{tabular}}
% Table options
\caption{Elasticity Values}
\label{table:PV_mod_STC_comp2}
% Center the table
\centering
% Stretch the table (vertically)
\renewcommand{\arraystretch}{1.3}
\toprule
\bigstrut\textbf{Customer type} &
\multicolumn{2}{c}{\bigstrut\textbf{Set 1}} &
\multicolumn{2}{|c}{\bigstrut\textbf{Set 2}} \\
\midrule
Residential & $-0.09$ to $-0.5$   & $-0.12$ to $-1.56$  & 1 & 2 \\
\midrule
Commercial  & $-0.019$ to $-0.25$ & $-0.44$ to $-0.97$  & 3 & 4 \\
\midrule
Industrial  & $-0.005$ to $-0.14$ & $-0.34$ to $-5.48$  & 5 & 6 \\
\bottomrule
\end{tabular}
\end{table*}
\end{document}


• If you use booktabs, please remove all those vertical lines. – TeXnician Jul 3 '17 at 6:25

Like this? I used >{\hsize=xₖ\hsize}X to adjust the widths of X columns, the condition on the xₖ coefficients being that their sum is equal to the number of X columns (this works as a system of barycentric coordinates):

\documentclass{report}
\usepackage{amsmath}
\usepackage{amssymb, amsfonts}
\usepackage[flushleft]{threeparttable}
\usepackage{makecell, caption}
\captionsetup{skip=6pt}
\usepackage{ragged2e}
\usepackage{tabularx}
\newcolumntype{L}{ >{ \arraybackslash \RaggedRight } X } % left justified
\newcolumntype{C}{ >{ \arraybackslash \Centering\hsize=1.6\hsize} X } % centered
\newcolumntype{y}{ >{ \arraybackslash \Centering\hsize=0.4\hsize} X } % centered
\newcolumntype{R}{ >{ \arraybackslash \RaggedLeft } X } % right justified
\newcolumntype{J}{ >{ \arraybackslash \justifying } X } % justified
\renewcommand \tabularxcolumn [1] { >{ \centering } m{#1} }
\usepackage{booktabs}
\newcolumntype{A}[1]{ >{ \arraybackslash \RaggedRight } m{#1} }
\newcolumntype{S}[1]{ >{ \arraybackslash \Centering } m{#1} }
\newcolumntype{D}[1]{ >{ \arraybackslash \RaggedLeft } m{#1} }
\newcolumntype{F}[1]{ >{ \arraybackslash \justifying } m{#1} }
\usepackage{multirow}

\begin{document}

\begin{table*}[]
% Table options
\caption{Elasticity Values}
\label{table:PV_mod_STC_comp2}
% Center the table
\centering
% Stretch the table (vertically)
\renewcommand{\arraystretch}{1.3}
\toprule
\multirow{2}{*}{
\textbf{Customer type}
} &
\multicolumn{2}{c}{
\multirow{2}{*}{\textbf{Set 1}}
}
&
\multicolumn{2}{|c}{
\multirow{2}{*}{\textbf{Set 2}}
}
\\
\multicolumn{1}{c|}{} &
\multicolumn{2}{c}{} &
\multicolumn{2}{|c}{}
\\
\Xhline{0.2 mm}
\textbf{Residential} &
$-0.09$ to $-0.5$ &
$-0.12$ to $-1.56$ & $1$ & $2$
\\
\Xhline{0.2 mm}
\textbf{Commercial} & $-0.019$ to $-0.25$ & $-0.44$ to $-0.97$ & $3$ & $4$
\\
\Xhline{0.2 mm}
\textbf{Industrial} & $-0.005$ to $-0.14$ & $-0.34$ to $-5.48$ & $5$ &
$6$
\\
\bottomrule
\end{tabularx}
\end{table*}

\end{document}


• Thanks for the answer. Even though the code does the job, it is still not general, that is, any change in the number of C columns means that the commands in the preamble must also be changed so that \hsize sum to the new number of C columns. For multiple tables, this solution will no longer be valid and many tables will not have their columns width equalized. – Al-Motasem Aldaoudeyeh Jul 3 '17 at 0:56

tabularx X columns (and tabulary which is closer to what you ask for), like standard tabular p columns are designed for allowing line breaking within a column to a specified or calculated width, but you almost never want automatic line breaking in tables of numeric data. A standard tabular l,r,c column automatically adjusts to the width of the column content.

\documentclass{report}

\usepackage{amsmath}
\usepackage{amssymb, amsfonts}
\usepackage[flushleft]{threeparttable}
\usepackage{makecell}

\usepackage{booktabs}

\begin{document}

\begin{table*}

% Table options
\caption{Elasticity Values}
\label{table:PV_mod_STC_comp2}

% Center the table
\centering

% Stretch the table (vertically)
\renewcommand{\arraystretch}{1.3}

\begin{tabular}{>\bfseries rcccc }
\toprule
Customer type&
\multicolumn{2}{c}{\textbf{Set 1}}&
\multicolumn{2}{c}{\textbf{Set 2}}\\
\midrule
Residential&
$-0.09$ to $-0.5$ &
$-0.12$ to $-1.56$ & $1$ & $2$
\\
\midrule
Commercial & $-0.019$ to $-0.25$ & $-0.44$ to $-0.97$ & $3$ & $4$
\\
\midrule
Industrial & $-0.005$ to $-0.14$ & $-0.34$ to $-5.48$ & $5$ &
$6$
\\
\bottomrule
\end{tabular}

\end{table*}

\end{document}


What you need is a tabulary. The width of tabulary columns is proportional to the natural width of the longest entry in each column. Here, you don't calculate any thing manually. The allowed headers are LCJR, the three L,C,R are what their names suggest and J is like the normal p, all in CAPITALS.

Notes:

• When using \multicolumns, the width of the combined columns should not exceed the natural width of their separate counterparts. Observe the \makebox[.7em]{$1$} I used to increase the width a bit. Also, normal letters c,l,r,p are used for combined columns.
• To increase the height of first row a simple \parbox{0pt}{\rule{0pt}{1cm}} can do this.
• Finally, vertical rules shouldn't be used with \toprule or \bottomrule, these create a small gap under/above the horizontal line.

-

\documentclass{report}

\usepackage{amsmath}
\usepackage{amssymb, amsfonts}
\usepackage[flushleft]{threeparttable}
\usepackage{makecell,tabulary}

\usepackage{ragged2e}
\usepackage{tabularx}
\usepackage{booktabs}
\usepackage{multirow}
\begin{document}

\begin{table*}    % [ ] Table options
\caption{Elasticity Values}
\label{table:PV_mod_STC_comp2}
\centering                                                % Center the table
\renewcommand{\arraystretch}{1.3} % Stretch the table (vertically)
\begin{tabulary}{\textwidth}{ R|C|C|C|C}
\Xhline{1pt}
\textbf{Customer type}\parbox{0pt}{\rule{0pt}{1cm}}&\multicolumn{2}{c|}{\textbf{Set 1}} & \multicolumn{2}{c}{\textbf{Set 2}}\\
\hline\textbf{Residential} & $-0.09$  to $-0.5$  & $-0.12$ to $-1.56$ & \makebox[.7em]{$1$} & $2$\\
\hline\textbf{Commercial}  & $-0.019$ to $-0.25$ & $-0.44$ to $-0.97$ & $3$ & $4$   \\
\hline\textbf{Industrial}  & $-0.005$ to $-0.14$ & $-0.34$ to $-5.48$ & $5$ & $6$   \\
\Xhline{1pt}
\end{tabulary}
\end{table*}

\end{document}