我正在尝试制作一个堆叠条形图,其中条形为全宽,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 之类的东西?
但我并不认为它有太大的帮助。
有效的方法:
- 条形宽度的绝对值(或根本没有条形宽度)
- 没有符号 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 }%
通过使用此宏,pgf图将计算 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}
输出: