代码

代码

我正在使用 pgfplots 自动生成一堆图。对于某些数据集,一个轴 (y) 上的数据跨度相对较小(相对于绝对值而言),因此 pgfplots 在打印该轴上的数字时会输出荒谬的数字重复(见图,-1.41 重复 4 次)。

轴上的重复数字

当然,一种选择是增加数字的格式精度,添加数字。问题是,可以通过选项中的某些选项自动设置精度吗axis

这可能导致必要数字的数量不受限制,从而引出第二个问题:是否有一种简单的方法可以自动选择参考基值并将其“添加”到缩放比例中(例如,$\cdot 10^8 - 10^7$而不是$\cdot 10^7$在示例中)。

梅威瑟:

\documentclass[]{article}
\usepackage[]{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot coordinates {
 ( 10, -14136746 )
 ( 72.421875, -14136749 )
 ( 166.054688, -14136829 )
 ( 228.476562, -14137018 )
 ( 290.898438, -14137366 )
};
\end{axis}
\end{tikzpicture}
\end{document}

答案1

这只是 Roald 版本 (expl3-side) 的清理版本。我编写了一个计算文件精度的命令(在包含文件之前使用)。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\usepackage{xparse}

\ExplSyntaxOn
\fp_new:N \l__roald_ymax_fp
\fp_new:N \l__roald_ymin_fp
\fp_new:N \l__roald_diff_fp
\fp_new:N \l__roald_nmax_fp
\fp_new:N \l__roald_precision_fp

\cs_generate_variant:Nn \fp_set:Nn { NV }

% From Jake (adapted): https://tex.stackexchange.com/questions/24910/find-a-extremal-value-in-external-data-file-with-pgfplot
\DeclareDocumentCommand { \precisionforfile } { m }
  {
    % max
    \pgfplotsforeachungrouped \table in {#1} {
        \pgfplotstablevertcat{\concatenated}{\table}
    }
    \pgfplotstablesort[sort~key={1},sort~cmp={float~>}]{\sorted}{\concatenated}
    \pgfplotstablegetelem{0}{1}\of{\sorted}
    \fp_set:NV \l__roald_ymax_fp \pgfplotsretval
    % min
    \pgfplotsforeachungrouped \table in {#1} {
        \pgfplotstablevertcat{\concatenated}{\table}
    }
    \pgfplotstablesort[sort~key={1},sort~cmp={float~<}]{\sorted}{\concatenated}
    \pgfplotstablegetelem{0}{1}\of{\sorted}
    \fp_set:NV \l__roald_ymin_fp \pgfplotsretval
    % calc
    \fp_set:Nn \l__roald_nmax_fp { ceil ( ln ( abs( \l__roald_ymax_fp ) ) / ln ( 10 ) ) + 1 }
    % Number of digits in the difference
    \fp_set:Nn \l__roald_diff_fp { ceil ( ln ( abs( \l__roald_ymax_fp - \l__roald_ymin_fp ) ) / ln ( 10 ) ) }
    % Calculate the precision
    \fp_set:Nn \l__roald_precision_fp { \l__roald_nmax_fp - \l__roald_diff_fp }
    \def\precision{\fp_to_int:N \l__roald_precision_fp}
  }
\ExplSyntaxOff

\begin{filecontents}{dataA.dat}
    10          -14135746
    72.421875   -14136100
    166.054688  -14136829
    228.476562  -14137018
    290.898438  -14137701
\end{filecontents}

\begin{filecontents}{dataB.dat}
    10          -14136846
    72.421875   -14136949
    166.054688  -14136829
    228.476562  -14136718
    290.898438  -14136866
\end{filecontents}

\begin{document}

\precisionforfile{dataA.dat}

\begin{tikzpicture}
    \begin{axis}[
        y tick label style={
            /pgf/number format/.cd,
            fixed,
            zerofill,
            precision=\precision,
            /tikz/.cd,},
        title={dataA.dat, Precision=\precision}]

        \addplot table[] {dataA.dat};
    \end{axis}
\end{tikzpicture}
\end{document}

更新:新版本支持坐标输入。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\usepackage{xparse}

\ExplSyntaxOn
\fp_new:N \l__roald_ymax_fp
\fp_new:N \l__roald_ymin_fp
\fp_new:N \l__roald_nmax_fp

\fp_new:N \l_roald_precision_fp

\cs_generate_variant:Nn \regex_split:nnN { nxN }
\cs_generate_variant:Nn \fp_set:Nn { Nx }

\DeclareDocumentCommand { \precisionforcoord } { m }
  {
    \fp_zero:N \l__roald_ymin_fp
    \fp_zero:N \l__roald_ymax_fp
    \regex_split:nxN { \( } { #1 } \l_tmpa_seq
    \seq_remove_all:Nn \l_tmpa_seq { ~ }
    \seq_map_inline:Nn \l_tmpa_seq
      {
        \tl_set:Nn \l_tmpa_tl { ##1 }
        \tl_replace_all:Nnn \l_tmpa_tl { ) } { }
        \regex_split:nxN { \, } { \l_tmpa_tl } \l_tmpb_seq
        \fp_set:Nx \l_tmpa_fp { \seq_item:Nn \l_tmpb_seq { 2 } }
        \fp_compare:nT { \l__roald_ymin_fp = 0 } { \fp_gset_eq:NN \l__roald_ymin_fp \l_tmpa_fp }
        \fp_compare:nT { \l__roald_ymax_fp = 0 } { \fp_gset_eq:NN \l__roald_ymax_fp \l_tmpa_fp }
        \fp_compare:nT { \l_tmpa_fp > \l__roald_ymax_fp } { \fp_gset_eq:NN \l__roald_ymax_fp \l_tmpa_fp }
        \fp_compare:nT { \l_tmpa_fp < \l__roald_ymin_fp } { \fp_gset_eq:NN \l__roald_ymin_fp \l_tmpa_fp }
      }
    \fp_set:Nn \l__roald_nmax_fp { ceil ( ln ( abs( \l__roald_ymax_fp ) ) / ln ( 10 ) ) + 1 }
    \fp_set:Nn \l_roald_precision_fp { \l__roald_nmax_fp - ( ceil ( ln ( abs( \l__roald_ymax_fp - \l__roald_ymin_fp ) ) / ln ( 10 ) ) ) }
    \def\precision{\fp_to_int:N \l_roald_precision_fp}
  }
\ExplSyntaxOff

\def\coordinatesa{
    (10,          -14135746)
    (72.421875,   -14136100)
    (166.054688,  -14136829)
    (228.476562,  -14137018)
    (290.898438,  -14137701)
}

\def\coordinatesb{
    (10,          -14136846)
    (72.421875,   -14136949)
    (166.054688,  -14136829)
    (228.476562,  -14136718)
    (290.898438,  -14136866)
}

\begin{document}
\precisionforcoord{\coordinatesa}
\begin{tikzpicture}
    \begin{axis}[
        y tick label style={
            /pgf/number format/.cd,
            fixed,
            zerofill,
            precision=\precision,
            /tikz/.cd,},
        title={A, Precision=\precision}]
        \addplot coordinates \coordinatesa;
    \end{axis}
\end{tikzpicture}
\vskip2em
\precisionforcoord{\coordinatesb}
\begin{tikzpicture}
    \begin{axis}[
        y tick label style={
            /pgf/number format/.cd,
            fixed,
            zerofill,
            precision=\precision,
            /tikz/.cd,},
        title={B, Precision=\precision}]
        \addplot coordinates \coordinatesb;
    \end{axis}
\end{tikzpicture}
\end{document}

对于新版本,您需要安装最新的 expl3 (TL17)。如果您使用的是更新到冻结状态的旧发行版(例如 TL16),则可以更改\pgfplotsset{compat=1.15}\pgfplotsset{compat=1.14}并包含\usepackage{l3regex}。注意:后一个软件包将来可能会从发行版中删除。


更新 2:我刚刚引入了一个几乎即时的命令来替代您的 addplot。唯一的问题是它包括轴环境(您无法在那里添加另一个图),因为 y 标签必须在那里作为选项进行调整。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\usepackage{xparse}

\ExplSyntaxOn
\fp_new:N \l__roald_ymax_fp
\fp_new:N \l__roald_ymin_fp
\fp_new:N \l__roald_nmax_fp

\fp_new:N \l_roald_precision_fp

\cs_generate_variant:Nn \regex_split:nnN { nxN }
\cs_generate_variant:Nn \fp_set:Nn { Nx }

\DeclareDocumentCommand { \precisionforcoord } { m }
  {
    \fp_zero:N \l__roald_ymin_fp
    \fp_zero:N \l__roald_ymax_fp
    \regex_split:nxN { \( } { #1 } \l_tmpa_seq
    \seq_remove_all:Nn \l_tmpa_seq { ~ }
    \seq_map_inline:Nn \l_tmpa_seq
      {
        \tl_set:Nn \l_tmpa_tl { ##1 }
        \tl_replace_all:Nnn \l_tmpa_tl { ) } { }
        \regex_split:nxN { \, } { \l_tmpa_tl } \l_tmpb_seq
        \fp_set:Nx \l_tmpa_fp { \seq_item:Nn \l_tmpb_seq { 2 } }
        \fp_compare:nT { \l__roald_ymin_fp = 0 } { \fp_gset_eq:NN \l__roald_ymin_fp \l_tmpa_fp }
        \fp_compare:nT { \l__roald_ymax_fp = 0 } { \fp_gset_eq:NN \l__roald_ymax_fp \l_tmpa_fp }
        \fp_compare:nT { \l_tmpa_fp > \l__roald_ymax_fp } { \fp_gset_eq:NN \l__roald_ymax_fp \l_tmpa_fp }
        \fp_compare:nT { \l_tmpa_fp < \l__roald_ymin_fp } { \fp_gset_eq:NN \l__roald_ymin_fp \l_tmpa_fp }
      }
    \fp_set:Nn \l__roald_nmax_fp { ceil ( ln ( abs( \l__roald_ymax_fp ) ) / ln ( 10 ) ) + 1 }
    \fp_set:Nn \l_roald_precision_fp { \l__roald_nmax_fp - ( ceil ( ln ( abs( \l__roald_ymax_fp - \l__roald_ymin_fp ) ) / ln ( 10 ) ) ) }
    \def\precision{\fp_to_int:N \l_roald_precision_fp}
  }
\DeclareDocumentCommand { \axisplot } { O{} m }
  {
    \precisionforcoord{#2}
    \begin{axis}[y~tick~label~style={
            /pgf/number~format/.cd,
            fixed,
            zerofill,
            precision=\precision,
            /tikz/.cd,},#1]
      \addplot coordinates #2;
    \end{axis}
  }
\ExplSyntaxOff

\def\coordinatesa{
    (10,          -14135746)
    (72.421875,   -14136100)
    (166.054688,  -14136829)
    (228.476562,  -14137018)
    (290.898438,  -14137701)
}

\def\coordinatesb{
    (10,          -14136846)
    (72.421875,   -14136949)
    (166.054688,  -14136829)
    (228.476562,  -14136718)
    (290.898438,  -14136866)
}

\begin{document}
\begin{tikzpicture}
\axisplot[title={A, Precision=\precision}]{\coordinatesa}
\end{tikzpicture}
\vskip1em
\begin{tikzpicture}
\axisplot[title={B, Precision=\precision}]{\coordinatesb}
\end{tikzpicture}
\end{document}

精确

答案2

这个答案应该回答问题1。

精度可以通过 作为轴选项来设置/pgf/number format/.cd,fixed,precision=<some value>

这里有些例子:

\documentclass[]{article}
\usepackage{pgfplots}
\begin{document}
\centering
\foreach \precision in {4,5,6,7}
{
\begin{tikzpicture}
\begin{axis}[/pgf/number format/.cd,fixed,precision=\precision,
title={Precision=\precision}
]
\addplot coordinates {
 ( 10, -14136746 )
 ( 72.421875, -14136749 )
 ( 166.054688, -14136829 )
 ( 228.476562, -14137018 )
 ( 290.898438, -14137366 )
};
\end{axis}
\end{tikzpicture}
}
\end{document}

结果:

在此处输入图片描述

答案3

我可能有一个解决方案,尽管当前的代码非常丑陋,因为我对宏、计算和存储值不是很熟悉。

代码的工作原理如下。它查看数据集中最大 y 值的位数 ( \nmax)。然后计算位数:\ymax - \ymin( ndiff)。然后有效位数由以下公式给出:\nmax - \ndiff

代码

\documentclass[]{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\usepackage{pgfplotstable}
\usepackage{filecontents}
\usepackage[nomessages]{fp}
\usepackage{xparse}

% From https://tex.stackexchange.com/questions/197844/rounding-a-number-to-its-hundred
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\ceil}{m}
{
    \fp_eval:n { ceil ( #1 ) }
}
\ExplSyntaxOff

\newcommand{\logten}[1]
{
    \FPeval\res{ ln( abs(#1) ) / ln( 10 ) }
}

% From Jake: https://tex.stackexchange.com/questions/24910/find-a-extremal-value-in-external-data-file-with-pgfplot
\newcommand{\findmax}[1]{
    \pgfplotsforeachungrouped \table in {#1} {%
        \pgfplotstablevertcat{\concatenated}{\table}%
    }%
    \pgfplotstablesort[sort key={1},sort cmp={float >}]{\sorted}{\concatenated}%
    \pgfplotstablegetelem{0}{1}\of{\sorted}%
    \let\ymax=\pgfplotsretval%
}
\newcommand{\findmin}[1]{
    \pgfplotsforeachungrouped \table in {#1} {%
        \pgfplotstablevertcat{\concatenated}{\table}%
    }%
    \pgfplotstablesort[sort key={1},sort cmp={float <}]{\sorted}{\concatenated}%
    \pgfplotstablegetelem{0}{1}\of{\sorted}%
    \let\ymin=\pgfplotsretval%
}

\begin{filecontents}{dataA.dat}
    10          -14135746
    72.421875   -14136100
    166.054688  -14136829
    228.476562  -14137018
    290.898438  -14137701
\end{filecontents}

\begin{filecontents}{dataB.dat}
    10          -14136846
    72.421875   -14136949
    166.054688  -14136829
    228.476562  -14136718
    290.898438  -14136866
\end{filecontents}

\begin{document}

\findmax{dataA.dat}
\findmin{dataA.dat}

% number of digits in \ymax
\logten{\ymax}
\def\nmax{\ceil{\res}}
\FPeval{\nmax}{(nmax) + 1}

% Number of digits in the difference
\FPeval{\diff}{(\ymax) - (\ymin)}%   
\logten{\diff}
\def\ndiff{\ceil{\res}}

% Calculate the precision
\FPeval\precision{clip(nmax - ndiff)}

\begin{tikzpicture}
    \begin{axis}[
        y tick label style={
            /pgf/number format/.cd,
            fixed,
            zerofill,
            precision=\precision,
            /tikz/.cd,},
        title={dataA.dat, Precision=\precision}]

        \addplot table[] {dataA.dat};
    \end{axis}
\end{tikzpicture}
\end{document}

两个数据集的结果

数据A数据B

漏洞

该代码适用于一个数据集,但如果我在同一文档中的第二个数据集上运行该函数\findmin或,它有时会返回旧的或。\findmax\ymin\ymax

相关内容