[comp.text.tex] Decimal Alignment in LaTeX tables

bed_gdg@SHSU.BITNET ("George D. Greenwade") (04/27/91)

On Sat, 27 Apr 91 09:38:39 CST, Charles H. Franklin <C38871CF@WUVMD.BITNET>
asks:
> For some considerable time I've been looking for a style that allows
> columns of a LaTeX table to be aligned on the decimal point, rather than
> left, right, or center.  The need arises all the time in my work where it
> is conventional to present parameter estimates as follows
>...
> So, Once More, I ask if anyone has or knows of a style file which modifies
> the ctabular environment to allow for decimal alignment in addition to the
> l,r,c alignments which are native to LaTeX.
 
There is a file, decalign.sty, which does precisely this by defining d (in
addition to tabular's l,c,r,p) for decimal aligned columns.  It does this
by creating two column, with the "." acting as the "&" in this environment.
Note that this means {tabular}{lcd} is *really* a 4-column tabular if
you're going to use multicolumn ("d" resolves to r.l and works pretty good).
 
The style file and its readme file are available from FILESERV as
STY.DECALIGN and STY.DECALIGN_README (time to be embarrassed; I put them
up, got them in our TEX$INPUTS, but forgot to include them in the
description listing -- sorry).  To retrieve both files, include the
wildcard request:
SENDME STY.DECALIGN*
in the body of a mail message to FILESERV@SHSU.BITNET.  If you just want
one of the files, use SENDME STY.filename (replacing filename with the
specific file you want, naturally).
 
Regards and hope this helps,   George
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
George D. Greenwade, Ph.D.                            Bitnet:  BED_GDG@SHSU
Department of Economics and Business Analysis         THEnet: SHSU::BED_GDG
P. O. Box 2118                                        Voice: (409) 294-1266
Sam Houston State University                          FAX:   (409) 294-3612
Huntsville, TX 77341            Internet: bed_gdg%shsu.decnet@relay.the.net
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

C38871CF@WUVMD.BITNET ("Charles H. Franklin") (04/27/91)

For some considerable time I've been looking for a style that
allows columns of a LaTeX table to be aligned on the decimal
point, rather than left, right, or center.  The need arises all
the time in my work where it is conventional to present parameter
estimates as follows
 
     X1        0.370
  se(X1)      (0.187)
 
etc.
 
I've "solved" the problem with a cnudge command which appends space to
the parameter estimate equal to the width of the ), but this is not
nice, is a pain to add to each parameter estimate, and does not serve in
all cases. (Some editors, for example, want an asterisk next to parameters
twice their standard errors.)
 
So, Once More, I ask if anyone has or knows of a style file which
modifies the ctabular environment to allow for decimal alignment in
addition to the l,r,c alignments which are native to LaTeX.
 
If not, I may have reached the point of trying to create such a style
myself, and if I do, it will NOT be a Pretty Sight. So please, save the
world from the Horror Style from St. Louis.
 
Thanks,
cchf
 
Charles H. Franklin
Washington University
C38871CF@WUVMD.Bitnet

raja@copper.ucs.indiana.edu (Raja Sooriamurthi) (04/27/91)

C38871CF@WUVMD.BITNET ("Charles H. Franklin") writes:

>For some considerable time I've been looking for a style that
>allows columns of a LaTeX table to be aligned on the decimal
>point, rather than left, right, or center.  

This was asked a few months ago and the below style file was posted.
I've never used it my self but hope it helps. - Raja
----------------------------------------------------------------------

	One of the people in our computer section found the following
stuff somewhere a loooong time ago. Anyway, it allows you to use
'd' in the column description the same way as 'l' 'r' and 'c'. This
provides you with decimal point alignment of numbers (or commas, for the
Europeans out there, who don't like decimal points, or any other character)

What follows: (i) a system message describing 'decalign.sty', (ii) an
example file in LaTeX and (iii) the decalign.sty file itself. 

The example is, I think, excessively complex. Just use 'd' in place of
'lrc' in the usual way.

Hope it helps ! If the originator of this stuff recognises his/her work, please
step forward for the recognition you deserve.

Any questions should be sent to Stephen Meatheringham (sjm@merlin.anu.edu.au)
 - our computer section TeX guru. (He doesn't know I said that :-) )

===============================================================================
 Markus Buchhorn                                           ///  | This space
 Mt Stromlo and Siding Spring Observatories, Canberra     ///   | 
 PMB Weston Ck. P.O. A.C.T. 2611, Australia           \\\///    | intentionally
 markus@mso.anu.edu.au                                 \XX/     | left blank
===============================================================================

Begin include:
-----------------------------------------------------------------------------

System message:

A problem occurs in TEX and LATEX when you try to align columns in a table on
the decimal point (or any other character).   There is now a document style
option in LATEX called `decalign', which adds a new column specifier to the
tabular and array environments.  Use a `d' to indicate that a column should
contain entries aligned on the decimal point.  An optional character after the
`d' indicates the character to be used as the separator; the default is a
period.  To use this option simply put :
   \documentstyle[decalign]{report}    <---- decalign in the document style

Use a `d' to indicate that a column should contain entries aligned on the
decimal point.  An optional character after the d indicates the character to be
used as the separator; the default is a period, but Europeans will probably use
commas. 

To align along the decimal point in plain TeX, define two columns in the
template like this:
  &\catcode`.=4 \tabskip0pt \hfil#&.#\hfil\tabskip=<whatever> &

                                 Stephen Meatheringham

-----------------------------------------------------------------------------
Example document:

\documentstyle[decalign]{report}

\begin{document}

\begin{tabular}{|r||r@{--}l|p{1.2in}|d,|}   % Separator will be a comma.
\hline
\multicolumn{6}{|c|}{GG\&A Hoofed Stock}
  \\ \hline\hline
&\multicolumn{2}{c|}{Price}& &
\multicolumn{2}{c|}{}              % Must treat the d column as two columns.
\\ \cline{2-3}
\multicolumn{1}{|c||}{Year}
& \multicolumn{1}{l@{\,\vline\,}}{high}
& low & \multicolumn{1}{c|}{Comments} & \multicolumn{2}{c|}{Other}  % here too.
  \\ \hline
1971 & 97 & 245 & Bad year for farmers in the west. & 23,45 \\ \hline
72 & 245 & 245 & Light trading due to a heavy winter. & 435,23 \\ \hline
73 & 245 & 2001 & No gnus was very good gnus this year. & 3,8756 \\ \hline
\end{tabular}

\end{document}

%  There are a few caveats.  The `column' is actually two columns, so one
%  must remember that when using \multicolumn or \cline.  Also, to skip
%  the column, you can't just put an ampersand, because that will only skip
%  one column.  You can't put two ampersands, either, because the separator
%  is automatically included as the first thing in the second column.  You
%  must use \multicolumn{2}.  None of the other column specifiers can be used
%  as separators, and the use of certain characters (&, {, }, #, etc.) will
%  probably produce chaos.  This is not a severe inconvenience, because only
%  periods and commas are likely to be used.  Finally, the `d' specifier
%  makes no sense in the {col} argument of the \multicolumn command, and
%  will in fact wreak havoc there.

-----------------------------------------------------------------------------
DECALIGN.STY:



\typeout{Document Style option 'decalign', Released 1 October 1987}
\def\dsep{}  % This is necessary for some unknown reason.
\def\@testpach#1{\@chclass \ifnum \@lastchclass=\tw@ 4 \else
    \ifnum \@lastchclass=3 5 \else
     \z@ \if #1c\@chnum \z@ \else
                              \if #1l\@chnum \@ne \else
                              \if #1r\@chnum \tw@ \else
          \@chclass \if #1|\@ne \else
                    \if #1@\tw@ \else
                    \if #1p3 \else
                    \if #1d7 \else
                    \ifnum \@lastchclass=7 8 \else \z@ \@preamerr 0\fi
  \fi  \fi  \fi  \fi  \fi  \fi  \fi  \fi
\fi}
%  Additions to these macros handle the extra classes.
\def\@mkpream#1{\@firstamptrue\@lastchclass6
\def\@preamble{}\def\protect{\noexpand\protect\noexpand}\let\@sharp\relax
\let\@startpbox\relax\let\@endpbox\relax
\@expast{#1}\expandafter\@tfor \expandafter
  \@nextchar \expandafter:\expandafter=\@tempa\do{\@testpach\@nextchar
  \ifnum \@lastchclass=7 \ifnum \@chclass=8 \else\@classviii{.}\fi\fi
  \ifcase \@chclass \@classz \or \@classi \or \@classii \or \@classiii
    \or \@classiv \or\@classv \or \or\@classvii \or\@classviii{\@nextchar}%
    \fi\@lastchclass\@chclass}%
\ifcase \@lastchclass \@acol
    \or \or \@preamerr \@ne\or \@preamerr \tw@\or \or \@acol \fi}
\def\@tabular{\leavevmode \hbox \bgroup $\let\@acol\@tabacol
   \let\@classz\@tabclassz
   \let\@classiv\@tabclassiv
   \let\@classviii\@tabclassviii
   \let\\\@tabularcr\@tabarray}
\def\array{\let\@acol\@arrayacol \let\@classz\@arrayclassz
   \let\@classiv\@arrayclassiv
   \let\@classviii\@arrayclassviii
   \let\\\@arraycr\def\@halignto{}\@tabarray}
\def\@arrayclassz{\ifcase \@lastchclass \@acolampacol \or \@ampacol \or
   \or \or \@addamp \or
   \@acolampacol \or \@firstampfalse \@acol \or
   \@acolampacol \or \@acolampacol
   \fi
\edef\@preamble{\@preamble
  \ifcase \@chnum
     \hfil$\relax\@sharp$\hfil \or $\relax\@sharp$\hfil
    \or \hfil$\relax\@sharp$\fi}}
\def\@tabclassz{\ifcase \@lastchclass \@acolampacol \or \@ampacol \or
   \or \or \@addamp \or
   \@acolampacol \or \@firstampfalse \@acol \or
   \@acolampacol \or \@acolampacol
   \fi
\edef\@preamble{\@preamble
  \ifcase \@chnum
     \hfil\ignorespaces\@sharp\unskip\hfil
     \or \ignorespaces\@sharp\unskip\hfil
     \or \hfil\hskip\z@ \ignorespaces\@sharp\unskip\fi}}
\def\@classi{\ifcase \@lastchclass \@acol \@arrayrule \or
   \@addtopreamble{\hskip \doublerulesep}\@arrayrule\or
   \or \or \@arrayrule \or
   \@acol \@arrayrule \or \@arrayrule \or
   \@acol \@arrayrule \or \@acol \@arrayrule
   \fi}
\def\@classiii{\ifcase \@lastchclass \@acolampacol \or
   \@addamp\@acol \or
   \or \or \@addamp \or
   \@acolampacol \or \@ampacol \or
   \@acolampacol \or \@ampacol
   \fi}
\def\@classvii{\ifcase \@lastchclass \@acolampacol \or
   \@addamp\@acol \or
   \or \or \@addamp \or
   \@acolampacol \or \@ampacol \or
   \@acolampacol \or \@acolampacol \fi}
\def\@tabclassviii#1{\@addtopreamble{\catcode`#1=4 \hfil\ignorespaces\@sharp
   \unskip&#1\@sharp\unskip\hfil}}
\def\@arrayclassviii#1{\@addtopreamble{\catcode`#1=4 \hfil$\relax\@sharp$&
   $\relax.\@sharp$\hfil}}
%%%---------------End o' example file.
-----------------------------------------------------------------------------

C38871CF@WUVMD.BITNET ("Charles H. Franklin") (04/29/91)

Since asking about decimal alignment on Saturday I've received about a dozen
responses.  I can't believe how helpful you all are.  After trying
unsuccessfully several times in the past to get a solution to decimal
alignment, it is really nice to get so much help so fast.
 
From the comments in the replies, it seems I am not the only one who has
wanted decimal alignment. So I thought I would post a summary of the various
solutions so we can all see what the options appear to be.
 
1) Use \hphantom to add spaces where needed. eg
    \newcommand{\Z}{\hphantom{0}}
    \newcommand{\M}{\hphantom{$-$}}
then
    1.0\Z\Z    &   \M0.0003
    0.333      &   $-0.0001$
line up like you want.  {Note you can also do this for the ")" on the standard
errors in my example. This is essentially the solution I have been using.}
 
2) Use the @{.} argument in the tabular declaration to create two columns with
no spaces and a decimal point between them. eg
          \begin{tabular}{r@{.}l}
                  10&7 \\
                   1&3 \\
                   0&75
          \end{tabular}
produces
                  10.7
                   1.3
                   0.75
 
3) Use DECALIGN.STY (available from FILESERV@SHSU) which implements a "d"
alignment argument for the tabular environment. This "d" alignment type is in
fact a version of (2) above. It defines two columns with a decimal between
them and uses the decimal as the column separator, thus allowing you to write
3.14 instead of 3&14. This means that "d" is really r@{.}l, so you must
remember that it is in fact two columns instead of one, important when making
the headings for the column.
 
4) Follow the lead of REVTEX and define \dec x.xx which produces a box of
equal width on both sides of the decimal place. When used with a center
aligned column, this produces decimal alignment. To see the REVTEX code, scan
REVTEX.STY for the string "\dec". (Or see below.)
 
 
OK, those are the proposed solutions. Each will work. Obviously preferences
over these is partly subjective and I guess they depend on what you are used
to. But here are my own thoughts on the solutions, and a solution of my own.
 
1) The \hphantom space is what I've been doing. It suffers from having to
think too much in constructing tables, and more so from the problem of what to
do when you have too much, rather than too little, after the decimal. For
example, if an asterisk is used to indicate a statistically significant
coefficient, eg    2.227* then the problem with alignment is the asterisk
takes up too much space. Fixing this using phantom space is possible but
painful.
 
2) and 3)  The r@{.}l solution is attractive because it is built in to LaTeX.
The DECALIGN style is really the same thing but makes "d" do what r@{.}l does,
plus a little more. Either of these is workable. My objection is the fact that
this produces two columns masquerading as only one. I'm sure those who use
this solution quickly get used to it, but I think a column should be a column
and not two. With DECALIGN this is especially inconsistent, since "d" looks
just like "r" or "l" but it behaves quite differently.   This caused me
trouble when I tried DECALIGN on a table I had in a paper. The table used
blank cells for some coefficients which where estimated in one column but not
in others. This gave DECALIGN fits. Presumably because my one column of blank
cells was now only half of the expected two columns. Certainly I could fix it,
but I don't like that kind of inconsistency. I also don't like 3&14 in place
of 3.14, (though this can be avoided with DECALIGN), because it seems more
error prone.
 
4) \dec x.xx has the major drawback that you have to enter it for every cell
you want aligned on the decimal. A global declaration would be much nicer.
 
In the end, I've settled on 4) as the less worse solution. A "d" alignment
primitive in LaTeX is the obvious "right" solution, but is not available.
For me, I think the "two-columns-in-one" solution of 2) and 3) is just too
inconsistent with the rest of the information in the table. So I've opted for
the \dec x.xx solution, even though it has the problem of having to include it
in each cell. This seems to me better because it keeps the consistency of the
column declarations. Plus, the style file required to implement this is
much smaller than that for DECALIGN.
 
An unexpected benefit of using the \dec approach is that other entries in the
column need not be decimal aligned and are easily manipulated. For example, at
the bottom of a column of regression coefficients it is customary to have the
number of cases, the r-square and assorted other stuff. These entries are
probably best given right aligned, which is easily done when using \dec.
 
I've put together a little file called DECTAB.STY which is appended below. It
steals the \dec definitions from REVTEX and adds a little for convenience.
You may want to redefine \dec to \da or even \d to reduce the required typing
in tables. I've stuck with \dec simply for clarity. DECTAB.STY also provides
\la, \ra and \ca for local left, right and center alignment. This is often
convenient and again saves typing.
 
I've tried it for one whole day on my tables and it seems to work. Beyond
that, I offer no warranties. If you find problems with it, please let me know.
 
Once more, thanks to all who sent their advice. Even if I don't take it, I
have profited from it.
----------------------------Begin DECTAB.STY--------------------------------
% DECTAB.STY  (April 27, 1991)
% Allows decimal alignment in tabular environment
% \dec definitions taken from REVTEX.STY
% by Charles Franklin, April 27, 1991
% (C38871CF@WUVMD.WUSTL.EDU or C38871CF@WUVMD.Bitnet)
%
% USAGE:  For decimal alignment in a table, use \dec 3.14 for
%         the cell entry.  The column should be center aligned
%         to achieve the desired effect.
%         For example:
%
%         \begin{tabular}{lcc}
%
%         Constant          & \dec  -1.461    &  \dec  -0.724  \\
%         Standard Error    & \dec  (0.422)   &  \dec  (0.455) \\
%
%         Note that a `.' MUST appear for the alignment to work.
%         Use `\dec 520.' NOT `\dec 520' for integers.
%
%         DECTAB also defines \ra, \la, \ca for easy modification of
%         global alignments. These produce local right, left and center
%         alignments of the cell entry. If there are spaces in the cell
%         entry, enclose the contents in {...}, eg \la {This Column}
%
\typeout{Document Style Option `dectab', version April 27, 1991}
 
\newdimen\@Ldec \newdimen\@Rdec
 
\def\dec #1.#2 {\hbox to\@Ldec{\hss#1}\def\test{#2}%
\ifx\test\empty\hbox to\@Rdec{\hfill}\else\hbox to\@Rdec{.#2\hss}\fi
}
 
\def\setdec #1.#2 {\relax%
  \bgroup
    \setbox0\hbox{\kern1pt\relax#1}\setbox1\hbox{\kern1pt\relax#2}%
    \global\@Ldec\wd0\global\@Rdec\wd1%
  \egroup
}
 
\setdec 000.000 % default size of 3 digits on each side
 
% Following defs allow easy modification of global alignment in
% tables. \ra, \la, \ca for right, left and center alignments.
 
\def\ra #1 {\multicolumn{1}{r}{#1}}
\def\la #1 {\multicolumn{1}{l}{#1}}
\def\ca #1 {\multicolumn{1}{c}{#1}}
 
% end DECTAB.STY