11

As I understand it, using various options for the S column in siunitx, I may produce columns containing both numerical and nonnumerical entries. I may have the numerical entries aligned at their decimal points. I may have the text entries either left-, right-, or center- justified with respect to the column's width.

Is it possible to have the numerical entries aligned by their decimal, while controlling the text entries' alignment as it relates to the decimal marker?

To complicate things further, is it possible to apply alignments differently row by row? In particular, could I leave column-centered alignment for the head entry of a column, while making my special decimal marker-based alignment apply to later entries?

The following MWE sort of produces what I want with exaggerated numbers, but I have manually forced some space in the last two entries to make it happen. I want to not have to do this.

\documentclass{article}

\usepackage{siunitx}


\newcommand*\heading[1]{\multicolumn{1}{c}{#1}}

\begin{document}


\begin{tabular}{S[table-format=9.3,table-text-alignment=center]}
\hline
\heading{Title}\\
\hline
1\\
2.000\\
6\\
24.0\\
123456789\\
{\phantom{123\,456\,78}\vdots\phantom{\,000}}\\
{\phantom{123\,456\,7}$f(n)$\phantom{\,00}}
\end{tabular}

\end{document}

*enter image description here*

Note that I do want a centered title, and that ideally I actually want the remaining text entries centered with respect to a point that is roughly 0.5\ex to the left of the decimal marker. Also, note that since I have such asymmetry between integer an fractional parts, I do not think that table-number-alignment=center-decimal-marker is helpful.

David Carlisle
  • 757,742
alex.jordan
  • 2,179
  • Can you elaborate on what you meant with “apply alignments differently row by row”. Isn't that what you get with your \heading macro? – Qrrbrbirlbel Oct 27 '12 at 00:01
  • @Qrrbrbirlbel Thanks for your answer - I will try to apply it Monday when I again have access to my desktop. I believe that in my experiments, the text alignment from S was overriding the alignment c in my \heading macro. As I recall parameters like table-text-alignment=left made the c in my \heading command pointless. I may be misremembering though - I went through a lot of experimentation this morning. – alex.jordan Oct 27 '12 at 02:21
  • I just updated my answer so that is easier useable. If I understand it correctly, \multicolumn overrides SIunitx's stuff. And “Title” was actually typeset centered to the whole column … – Qrrbrbirlbel Oct 27 '12 at 02:28
  • @Qrrbrbirlbel Sorry for the confusion - in my MWE the Title is centered fine, and even better, without any manual spacing. Ideally, I would like a siunitx solution to my problem with text-at-decimal alignment - perhaps defining a new fourth option for table-text-align. I want to emphasize that such a solution should leave my heading alone, and still be overrideable by \multicolumn. Hopefully, this is not actually an issue. – alex.jordan Oct 27 '12 at 02:35
  • Than just type {Title} or use your \multicolumn solution. Implementing this inside of SIunitx is out of my skillset as it uses heavily LaTeX3 code. This is probably something for the developer of SIunitx. – Qrrbrbirlbel Oct 27 '12 at 02:51
  • @alex.jordan Reading over the question and current answer, it seems this essentially boils down to a feature request. You seem to want an option table-text-align = decimal-center, so align text relative to the decimal. Is that correct? Different alignments in different parts of a column are not really possible in a fully-automated, as table content is collected before being processed at all. As such, you will probably have to handle table headings using \multicolumn with the option I suggest. – Joseph Wright Oct 27 '12 at 06:45
  • 1
    I'd also note that the business about wanting an alignment with offset is really outside of what siunitx was designed to handle. The intention of the S column is to align numerical columns, which it does a reasonable job of, but if you have very specific needs then there comes a point at which a custom solution is the best way forward. – Joseph Wright Oct 27 '12 at 06:59
  • 1
    Logged for v2.6: https://bitbucket.org/josephwright/siunitx/issue/205/align-text-based-on-decimal-marker (probably over the Christmas holidays). – Joseph Wright Oct 27 '12 at 17:23
  • @Joseph Wright At first I hoped there may be some way to access decimal alignment for text; some sort of width that was part of the package but not mentioned in the documentation. I suppose it is indeed a feature request though. Thank you for putting it under consideration! – alex.jordan Oct 27 '12 at 17:37

1 Answers1

10

Let me say two things before:

  1. This is not an only-siunitx solution. Sadly, table-text-alignment doesn't take decimal-marker :(
  2. I provide two macros:
    1. \widestparts{<digits before …>}{<… and after decimal marker>}
    2. \tcenter{<text to center at the decimal marker>}

This works now, thanks to Peter Grill's question, Martin Scharrer's answer and Peter's hint in the chat.

Manual aligning

You can add another \textcenter macro that takes three arguments:

  1. stuff before your actual text,
  2. stuff after your actual text (in the example below I also removed the decimal marker .), and
  3. stuff that gets actually typeset.

For example:

\newcommand*{\textcenter}[3]{{%
    \hphantom{\num{#1}}%
    \makebox[\widthof{.}][c]{#3}\hspace{-\decimalmarkerwidth}%
    \hphantom{\num[add-decimal-zero = false,add-integer-zero = false,scientific-notation = fixed]{#2}}%
}}

Code

\documentclass{article}
\usepackage{xcolor} % only for this example (redefinition of hphantom}
\usepackage{mathtools,calc,siunitx,ifthen}
\usepackage[T1]{fontenc}
% getting the width of the decimal marker: . or ,
\newlength{\decimalmarkerwidth}\settowidth{\decimalmarkerwidth}{.} % or ,

% remove the % in the next line to get gray phantoms
%\renewcommand\hphantom[1]{{\color[gray]{.7}#1}}

\newcommand*\heading[1]{\multicolumn{1}{c}{#1}} % not used anymore ... (but can used (without the multicolumn) for other formatting (bf, color, ...)

\makeatletter
\newcounter{alex@auxctr} % (Internal)

% \widestparts takes two arguments: #1 = number of digits before the decimal marker
                                  % #2 = number of digits after the decimal marker
\newcommand*{\widestparts}[2]{%
    \alex@widestpartauxloop{\alex@widestpartleft}{#1}{9}%
    \alex@widestpartauxloop{\alex@widestpartright}{#2}{0}%
}

% (Internal) \alex@widestpartauxloop loops over #2 and adds #2 times #3 to #1.
\newcommand*{\alex@widestpartauxloop}[3]{%
    \def\alex@WidestPartTemp{}\setcounter{alex@auxctr}{0}%
    \whiledo{\value{alex@auxctr}<#2}{\g@addto@macro\alex@WidestPartTemp{#3}\stepcounter{alex@auxctr}}%
    \xdef#1{\alex@WidestPartTemp}%
}

% \tcenter takes one argument: #1 = actual text that should be typeset
\newcommand*{\tcenter}[1]{{%
    \hphantom{\num{\alex@widestpartleft}}%
    \makebox[\widthof{.}][c]{#1}\hspace{-\decimalmarkerwidth}%
    \hphantom{\num[add-decimal-zero = false,add-integer-zero = false,scientific-notation = fixed]{.\alex@widestpartright}}%
}}
\makeatother

\usepackage{booktabs} % for \top-, \mid- and \bottomrule

\begin{document}
\widestparts{9}{3}
\begin{tabular}{S[table-format=9.3,table-text-alignment=center]}
    \toprule
             \tcenter{Title}            \\ \midrule
                    1                   \\
                  2.000                 \\
                    6                   \\
                   24.0                 \\
                123456789               \\
    \tcenter{$\smash{\vdotswithin{.}}$} \\ % \smash is used to hide the oversized vertical height of \vdots
             \tcenter{$f(n)$}           \\ \bottomrule
\end{tabular}
\end{document}

Output

Output with phantomed hidden stuff  Output with gray hidden stuff

Moriambar
  • 11,466
Qrrbrbirlbel
  • 119,821
  • Thanks for the answer. I can't play around with this until Monday, but at a glance I have a concern. I am working on a very long document with hundreds of tables like this. And I very much want a solution at the level of S. That is, I won't want to have to put anything more than a pair of braces around my non-numeric table entries, let siunitx and S detect what is numeric and what is not, and typeset accordingly. Can I modify S to wrap your tcenter around non-numeric entries? – alex.jordan Oct 27 '12 at 02:47
  • @alex.jordan: That might be a separate question, but you could possibly use the collcell package for that, although I don't think I have tried it with the S column. – Peter Grill Oct 27 '12 at 03:20