数学家

数学家

我正在尝试制作一个堆叠条形图,其中条形为全宽,x 坐标为符号。这是一个简单示例:

\documentclass{scrartcl}
\usepackage[includeheadfoot,left=15mm,right=15mm,top=-8mm,bottom=10mm,headheight=3cm,headsep=15mm,marginparsep=0mm,marginparwidth=0mm,footskip=0mm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}

\begin{document}

\pgfplotsset{width=\textwidth}
\begin{tikzpicture}[line cap=rect]
\begin{axis}[
ybar stacked,
bar width=1,
symbolic x coords={a,b,c,d,e,f,g},
]
\addplot coordinates {
(a, 39.000000)
(b, 30.200000)
(c, 39.000000)
(d, 30.200000)
(e, 33.300000)
(f, 30.000000)
(g, 32.900000)
};

\end{axis}
\end{tikzpicture}

\end{document}

然而,当我尝试用 lualatex 编译它时,我得到了

! 软件包 pgfplots 错误:抱歉,输入坐标“\pgfplots@loc@TMPa”未定义为“符号 x 坐标={a,b,c,d,e,f,g}... 可能是拼写错误?或者您的意思是 [normalized]\pgfplots@loc@TMPa 之类的东西?

但我并不认为它有太大的帮助。

有效的方法:

  1. 条形宽度的绝对值(或根本没有条形宽度)
  2. 没有符号 x 坐标,将 a..g 替换为 1..7。

所以现在我没什么可尝试的了。我忽略了什么?

答案1

问题从这里开始:

\def\pgfplots@bar@mathparse@#1#2{%
  \pgfmathparse{\pgfkeysvalueof{/pgf/#2}}%
  \ifpgfmathunitsdeclared
  \else
      \edef\pgfplots@bar@direction@choice@{#1}%
      \if N\pgfplots@bar@direction@choice@%
          \if a\pgfplots@bar@direction@choice
          \else
              \if x\pgfplots@bar@direction@choice
                  \def\pgfplots@bar@direction@choice@{y}%
              \else
                  \if y\pgfplots@bar@direction@choice
                      \def\pgfplots@bar@direction@choice@{x}%
                  \else
                      \pgfplotsthrow{invalid argument}{\pgfplots@bar@direction@choice@}{Sorry, the value of 'bar direction' is invalid}\pgfeov%
                  \fi
              \fi
          \fi
      \fi
      \if N\pgfplots@bar@direction@choice@%
          \pgfplots@bar@mathparse@error{#1}{#2}%
      \else
          \let\pgfplots@loc@TMPa=\pgfmathresult
          % ↓↓↓ notice this line ↓↓↓
          \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{\pgfplots@loc@TMPa}%
          % ↑↑↑ notice this line ↑↑↑
          \let\pgfplots@loc@TMPa=\pgfmathresult
          \if\pgfplots@bar@direction@choice@ x%   
              \pgfqpointxy@orig{\pgfplots@loc@TMPa}{0}%
              \edef\pgfmathresult{\pgf@sys@tonumber\pgf@x}%
          \else
              \pgfqpointxy@orig{0}{\pgfplots@loc@TMPa}%
              \edef\pgfmathresult{\pgf@sys@tonumber\pgf@y}%
          \fi
          %\edef\pgfplots@loc@TMPa{{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}}%
          %\expandafter\pgfmathveclen@\pgfplots@loc@TMPa
      \fi
  \fi
}%

通过使用此宏,将计算 ybars 的正确宽度,特别是当宽度以相对值给出时。

\csname pgfplotstransformdirection ...这就是您在代码中看到的原因。此宏由x coord trafo或定义。它将输入的 x 坐标转换为物理坐标。通常输入是一个数字(1.2);有时它是一个日期(2017-1-23);在您的情况下它应该是符号(b)。

但是您的输入是1,这不是预定义的符号坐标,所以您会看到错误。

要克服这个问题,不能bar width=b因为\pgfmathparse不知道是什么就简单地放弃b。一些可能的解决方案包括:

  • 等到包更新;或者

  • \pgfplots@bar@mathparse@通过将变换线替换为

        % ↓↓↓ notice this line ↓↓↓
        \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{[normalized]\pgfplots@loc@TMPa}%  
        % ↑↑↑ notice this line ↑↑↑

这甚至更好

        \ifx\pgfplots@symb@magic@prefix\undefined % test if symbolic coordinate
            \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{\pgfplots@loc@TMPa}%
        \else
            \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{[normalized]\pgfplots@loc@TMPa}%
        \fi

数学家

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

\begin{document}

\makeatletter

\def\pgfplots@bar@mathparse@#1#2{%
    \pgfmathparse{\pgfkeysvalueof{/pgf/#2}}%
    \ifpgfmathunitsdeclared
    \else
        \edef\pgfplots@bar@direction@choice@{#1}%
        \if N\pgfplots@bar@direction@choice@%
            \if a\pgfplots@bar@direction@choice
            \else
                \if x\pgfplots@bar@direction@choice
                    \def\pgfplots@bar@direction@choice@{y}%
                \else
                    \if y\pgfplots@bar@direction@choice
                        \def\pgfplots@bar@direction@choice@{x}%
                    \else
                        \pgfplotsthrow{invalid argument}{\pgfplots@bar@direction@choice@}{Sorry, the value of 'bar direction' is invalid}\pgfeov%
                    \fi
                \fi
            \fi
        \fi
        \if N\pgfplots@bar@direction@choice@%
            \pgfplots@bar@mathparse@error{#1}{#2}%
        \else
            \let\pgfplots@loc@TMPa=\pgfmathresult
            \ifx\pgfplots@symb@magic@prefix\undefined
                \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{\pgfplots@loc@TMPa}%
            \else
                \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{[normalized]\pgfplots@loc@TMPa}%
            \fi
            \let\pgfplots@loc@TMPa=\pgfmathresult
            \if\pgfplots@bar@direction@choice@ x%   
                \pgfqpointxy@orig{\pgfplots@loc@TMPa}{0}%
                \edef\pgfmathresult{\pgf@sys@tonumber\pgf@x}%
            \else
                \pgfqpointxy@orig{0}{\pgfplots@loc@TMPa}%
                \edef\pgfmathresult{\pgf@sys@tonumber\pgf@y}%
            \fi
        \fi
    \fi
}%

\begin{tikzpicture}
    \begin{axis}[
        ybar stacked,
        bar width=1,
        symbolic x coords={a,b,c,d,e,f,g},
    ]
    \addplot coordinates {
        (a, 39.000000)
        (b, 30.200000)
        (c, 39.000000)
        (d, 30.200000)
        (e, 33.300000)
        (f, 30.000000)
        (g, 32.900000)
    };
    \end{axis}
\end{tikzpicture}

\begin{tikzpicture}
    \begin{axis}[
        ybar stacked,
        bar width=1,
        xticklabels={a,b,c,d,e,f,g},
        xtick=data, % a tick for each bar
        typeset ticklabels with strut % all xticklabels on the same baseline
    ]
    \addplot coordinates {
        (1, 39.000000)
        (2, 30.200000)
        (3, 39.000000)
        (4, 30.200000)
        (5, 33.300000)
        (6, 30.000000)
        (7, 32.900000)
    };
    \end{axis}
\end{tikzpicture}

\end{document}

答案2

我绝不是 pgfplots 方面的专家,但我在 cmhughes 对另一个问题的回答中找到了解决此问题的方法:格式化 pgfplot 图表。更粗的条形和总宽度

symbolic y coords={A, B, C}可以不使用,而是指定ytick={0,1,2}yticklabels={A, B, C},这不会导致设置 时出现同样的问题bar width。当然,\addplot必须将行中的所有坐标更改为适当的数字,而不是符号。

适当修改问题中给出的 MWE:

\documentclass{scrartcl}
\usepackage[includeheadfoot,left=15mm,right=15mm,top=-8mm,bottom=10mm,headheight=3cm,headsep=15mm,marginparsep=0mm,marginparwidth=0mm,footskip=0mm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\begin{document}

\pgfplotsset{width=\textwidth}
\begin{tikzpicture}[line cap=rect]
\begin{axis}[
ybar stacked,
bar width=0.8,
xtick={0,1,2,3,4,5,6},
xticklabels={a,b,c,d,e,f,g},
]
\addplot coordinates {
(0, 39.000000)
(1, 30.200000)
(2, 39.000000)
(3, 30.200000)
(4, 33.300000)
(5, 30.000000)
(6, 32.900000)
};

\end{axis}
\end{tikzpicture}

\end{document}

输出:

在此处输入图片描述

相关内容