标准对数轴

标准对数轴

我有一个特别的问题,关于如何正确修改刻度标签的样式,以使其采用指数样式。我实际上想要的是,当刻度对应于值为 10 的倍数时,它们的样式为 10^n。

标准对数轴

在对数样式轴的标准设置下,tikz 刚开始在从 10^5 开始的标签上使用指数样式数字。较小的数字将打印为简单数字。

使用 pgf 的数字格式选项 sci 10e

当我这样做时(即取消注释 y 轴选项中的第一行),tikz 将以 1*10^n 格式打印所有刻度标签,这已经接近我想要的格式了。但我想去掉首因数“1*”,以获得更紧凑的表示。

使用 pgf 的数字格式选项 sci generic

实际上,根据 pgfplotstable 手册,这应该是首选选项,可以达到我想要达到的目的。但是当我这样做时(即取消注释 y 轴选项中的第二行),我得到了一些奇怪的刻度标签格式结果。

通过稍微摆弄一些 pgfmathparse,我能够达到我想要达到的点(即取消注释第三行),但我发现这不是一个很好的解决方案。

有人有什么想法吗,如何更聪明地解决这个问题?

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{datavisualization,datavisualization.formats.functions}

\begin{document}
\makeatletter
\begin{tikzpicture}
\datavisualization [
scientific axes,
all axes={length=6cm},
x axis={
            ticks and grid={
                            step=2,
                            minor steps between steps=1
                            },
            include value={0,20},
            },
%               
y axis={
            logarithmic,
            ticks and grid={
                            step=1,
                            minor steps between steps=8,
                            %tick typesetter/.code={\pgfkeys{/pgf/number format/.cd, sci, sci 10e}\pgfmathprintnumber{##1}},
                            %tick typesetter/.code={\pgfkeys{/pgf/number format/.cd, sci, sci generic={exponent={10^{##1}}}}\pgfmathprintnumber{##1}}
                            %tick typesetter/.code={\pgfkeys{/pgf/number format/.cd, sci, sci generic={exponent={0^{\pgfmathparse{int(round(log10(##1)))}\pgfmathresult}}}}\pgfmathprintnumber{##1}}
                            },
            },
visualize as line
]
data[separator=\space] {
x y
0 1E1
5 1E2
10 1E3
15 1E4
20 1E5
}
;
\end{tikzpicture}
\end{document}

所有行都注释掉了

在此处输入图片描述

取消注释第一行

tick typesetter/.code={\pgfkeys{/pgf/number format/.cd, sci, sci 10e}\pgfmathprintnumber{##1}},

在此处输入图片描述

取消注释第二行

tick typesetter/.code={\pgfkeys{/pgf/number format/.cd, sci, sci generic={exponent={10^{##1}}}}\pgfmathprintnumber{##1}}

在此处输入图片描述

取消注释第三行

tick typesetter/.code={\pgfkeys{/pgf/number format/.cd, sci, sci generic={exponent={0^{\pgfmathparse{int(round(log10(##1)))}\pgfmathresult}}}}\pgfmathprintnumber{##1}}

在此处输入图片描述

答案1

这是不是正确。相反,它是一种更干净的黑客技术,不会像问题中的代码那样在编译时出现错误。

按照手册第805页的例子,我们定义\mytypesetter如下:

\def\mytypesetter#1{% page 805
  \tikzset{%
    /pgf/number format/.cd,
    sci,
    sci generic={mantissa sep=,exponent={0^{##1}}}%
  }%
  \pgfmathprintnumber{#1}%
}

由于在这种情况下尾数始终等于1,因此设置mantissa sep为空值并将指数排版为而0^{<value>}不是10^{<value>}应该给出我们想要的结果。

这显然不是一个好的解决方案,而只是一种 hack,因为这根本不符合语义标记。事实上,它以一种特别糟糕的方式混淆了格式和内容。

然而,我们可以说

      tick typesetter/.code=\mytypesetter{##1},

如果我正确理解了需求的话,就能产生所需的输出。

修改了 y 轴的刻度格式

如果您希望在一个地方配置所有这些,您可以这样做,但您必须区分传递给 的第一个参数tick typesetter和传递给 的第一个参数/pgf/number format/sci generic。您不想将前者传递给后者,否则您最终会得到指数格式的整个数字,以及尾数部分和它前面的分隔符。

  y axis={
    logarithmic,
    ticks and grid={
      step=1,
      minor steps between steps=8,
      tick typesetter/.code={%
        \tikzset{%
          /pgf/number format/.cd,
          sci,
          sci generic={mantissa sep=,exponent={0^{####1}}}%
        }%
        \pgfmathprintnumber{##1}
      }
    },
  },

我倾向于不这样做,因为我发现这比第一个版本更难阅读,因为第一个版本将数字格式化的代码与轴定义中的数字处理分开。但是,如果您出于某种原因喜欢第二个版本,它会生成相同的输出。

完整代码:

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{datavisualization,datavisualization.formats.functions}
\def\mytypesetter#1{% page 805
  \tikzset{%
    /pgf/number format/.cd,
    sci,
    sci generic={mantissa sep=,exponent={0^{##1}}}%
  }%
  \pgfmathprintnumber{#1}%
}

\begin{document}
\begin{tikzpicture}
  \datavisualization [
  scientific axes,
  all axes={length=6cm},
  x axis={
    ticks and grid={
      step=2,
      minor steps between steps=1
    },
    include value={0,20},
  },
  y axis={
    logarithmic,
    ticks and grid={
      step=1,
      minor steps between steps=8,
      tick typesetter/.code=\mytypesetter{##1},
    },
  },
  visualize as line
  ]
  data[separator=\space] {
    x y
    0 1E1
    5 1E2
    10 1E3
    15 1E4
    20 1E5
  }
  ;
\end{tikzpicture}
\end{document}

答案2

终于得到了一个“正确”的版本。要按照我想要的方式生成刻度标签,您必须在较低级别的 pgf 上工作。基本上,您需要定义自己的排版程序,正如 cfr 在他的回答中已经提到的那样。基本上这很容易。您将要打印的数字传递给您的代码\pgfmathfloatparsenumber{#1}。然后,数字被分成标志、尾数和指数,\pgfmathfloattomacro{\pgfmathresult}{\F}{\M}{\E}并传递给预定义的宏。然后实际的数字打印由完成\pgfutilensuremath{10^\E}

需要注意的是:

这种数字打印方式只有在使用对数轴缩放且仅用于主要刻度时才是正确的!对于其他任何情况都是不正确的,因为数字的尾数完全被省略了!

编辑

在排字员的声明中添加了一些百分号,以防止创建不需要的空格,因为当使用排字员在正确的垂直轴上设置标签时,这些空格会造成干扰。

編輯2

添加了一些花括号,以\pgfutilensuremath{10^{\E}}防止打印负指数时出现问题

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{datavisualization,datavisualization.formats.functions}
\def\mytypesetter#1{%
  \newcommand{\F}{0}%
  \newcommand{\M}{1}%
  \newcommand{\E}{0}%
  \pgfmathfloatparsenumber{#1}%
  \pgfmathfloattomacro{\pgfmathresult}{\F}{\M}{\E}%
  \pgfutilensuremath{10^{\E}}%
}

\begin{document}
\begin{tikzpicture}
  \datavisualization [
  scientific axes,
  all axes={length=6cm},
  x axis={
    ticks and grid={
      step=2,
      minor steps between steps=1
    },
    include value={0,20},
  },
  y axis={
    logarithmic,
    ticks and grid={
      step=1,
      minor steps between steps=8,
      tick typesetter/.code=\mytypesetter{##1},
    },
  },
  visualize as line
  ]
  data[separator=\space] {
    x y
    0 1E1
    5 1E2
    10 1E3
    15 1E4
    20 1E5
  }
  ;
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容