Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In a plot, I have several vertically distributed nodes containing numbers with different numbers of digits before and after the decimal separator, and a trailing percent sign.

I would like to align these nodes horizontally along the decimal separator, similar to what can be done using the S column type in tables using the siunitx package. However, I do not want to use a table for the alignment, since the nodes are unevenly spaced vertically.

How can I align these nodes properly? I thought about somehow adding space before the numbers depending on the number of digits, but couldn't think of an elegant way of doing that without lots of manual work.

Here's a MWE:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}
What I have:

\begin{tikzpicture}
\begin{axis}[
    ymode=log,
    height=4cm, width=8cm,
    domain=1:10,
    axis lines=left,
    clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
    \addplot [black] {#1*x} node [anchor=west] {#1\,\%};
}
\end{axis}
\end{tikzpicture}

What I want:

\begin{tikzpicture}
\begin{axis}[
    ymode=log,
    domain=1:10,
    height=4cm, width=8cm,
    axis lines=left,
    clip=false
]
\addplot [black] {x*0.01} node [anchor=west] {\hphantom{10}0.01\,\%};
\addplot [black] {x*0.1} node [anchor=west] {\hphantom{10}0.1\,\%};
\addplot [black] {x*1} node [anchor=west] {\hphantom{00}1\,\%};
\addplot [black] {x*10} node [anchor=west] {\hphantom{0}10\,\%};
\addplot [black] {x*100} node [anchor=west] {100\,\%};
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this question
    
The siunitx package provides a macro for table-like output of numbers: \tablenum[table-format=3.2]{#1}\,\% However, this also aligns the % sign. –  Qrrbrbirlbel Jan 2 '13 at 3:03

2 Answers 2

up vote 21 down vote accepted

You can insert a padding command such as the following:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\makeatletter
\def\pad#1{\xpad#1.\relax#1\,\%}

\def\xpad#1.#2\relax{%
\ifnum0#1<10 \phantom{0}\fi
\ifnum0#1<100 \phantom{0}\fi
}

\makeatother

\begin{document}
What I have:

\begin{tikzpicture}
\begin{axis}[
    ymode=log,
    height=4cm, width=8cm,
    domain=1:10,
    axis lines=left,
    clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
    \addplot [black] {#1*x} node [anchor=west] {\pad{#1}};
}
\end{axis}
\end{tikzpicture}

\end{document}

or this version which takes a parameter for the number of digits to pad:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\makeatletter
\def\pad#1#2{\xpad#1#2.\relax#2\,\%}

\def\xpad#1#2.#3\relax{%
\count@#1\relax
\@tempcnta\@ne\relax
\loop
\ifnum\count@>\z@
\advance\count@\m@ne
\multiply\@tempcnta 10\relax
\ifnum0#2<\@tempcnta \phantom{0}\fi
\repeat
}

\makeatother

\begin{document}
What I have:

\begin{tikzpicture}
\begin{axis}[
    ymode=log,
    height=4cm, width=8cm,
    domain=1:10,
    axis lines=left,
    clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
    \addplot [black] {#1*x} node [anchor=west] {\pad{2}{#1}};
}
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
    ymode=log,
    height=4cm, width=8cm,
    domain=1:10,
    axis lines=left,
    clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
    \addplot [black] {#1*x} node [anchor=west] {\pad{3}{#1}};
}
\end{axis}
\end{tikzpicture}

\end{document}
share|improve this answer
    
Ah yes, that looks pretty good, thank you! Is there a way of making this a bit more flexible regarding the number of digits to be added? What if I decide to add another plot with a label of 10000, for example? –  Jake Jan 1 '13 at 23:52
    
@Jake you can also count the digits with David's wizardry or say, via xstring's \Strlen –  percusse Jan 1 '13 at 23:54
    
well yes you just need an input parameter that gives the number of digits that you are padding (so 2 in the MWE) give me a minute... –  David Carlisle Jan 1 '13 at 23:55

Here's a solution with LaTeX3:

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\pad}{O{3} >{\SplitArgument{1}{.}}m }
 {
  \leavevmode % because of `\hphantom`
  \jake_pad:nnn {#1} #2
 }
\cs_new_protected:Npn \jake_pad:nnn #1 #2 #3
 {
  \int_step_inline:nnnn { #1 - 1 } { -1 } { 1 }
   { \int_compare:nT { #2 < 1 \prg_replicate:nn { ##1 } { * 10 } } { \hphantom{0} } }
  #2\IfValueT{#3}{.#3}
 }
\ExplSyntaxOff

You use it as

\pad{10}\,\%

for padding to three digits, or

\pad[5]{1234}

for padding to five digits.

Example:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\pad}{O{3} >{\SplitArgument{1}{.}}m }
 {
  \leavevmode % for \hphantom
  \jake_pad:nnn {#1} #2
 }
\cs_new_protected:Npn \jake_pad:nnn #1 #2 #3
 {
  \int_step_inline:nnnn { #1 - 1 } { -1 } { 1 }
   { \int_compare:nT { #2 < 1 \prg_replicate:nn { ##1 } { * 10 } } { \hphantom{0} } }
  #2\IfValueT{#3}{.#3}
 }
\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    ymode=log,
    height=4cm, width=8cm,
    domain=1:10,
    axis lines=left,
    clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
    \addplot [black] {#1*x} node [anchor=west] {\pad{#1}\,\%};
}
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
The maximum number of digits for the integer part is 10. –  egreg Jan 2 '13 at 0:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.