将包含数字的节点按小数点分隔符对齐

将包含数字的节点按小数点分隔符对齐

在图中,我有几个垂直分布的节点,其中包含小数点分隔符前后不同位数的数字以及尾随的百分号。

我想将这些节点沿小数点分隔符水平对齐,类似于S使用包中的表格中的列类型可以执行的操作siunitx。但是,我不想使用表格进行对齐,因为节点在垂直方向上的间距不均匀。

我该如何正确对齐这些节点?我考虑过根据数字的数量在数字前添加空格,但如果不进行大量手动工作,就想不出一种优雅的方法来做到这一点。

以下是 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}

答案1

您可以插入如下填充命令:

\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}

或者这个版本,它接受一个需要填充的数字的参数:

\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}

答案2

以下是使用 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

你可以使用它作为

\pad{10}\,\%

填充至三位数,或

\pad[5]{1234}

填充至五位数字。

例子:

\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}

在此处输入图片描述

相关内容