pgfplots:纠正舍入问题

pgfplots:纠正舍入问题

我遇到了一个问题,标记消失,因为数据总数超过 100,而 xmax 设置为 100。请参阅pgfplots:由于舍入问题导致节点附近的坐标丢失

正如所引用问题的答案中所写,我试图通过将值标准化为 100 来避免该问题。但这导致之前正确的行中出现(小得多的)舍入误差,现在标记在那里消失了。请参见以下示例。在标准化之前,列 F 受到影响,列 B 受到影响。

我怎样才能可靠的有什么方法可以避免这种舍入问题?或者至少得到一个明确的错误消息。我有相当多的这种图,我不想一直检查它们是否有缺失的标记。

\documentclass{scrreprt}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\usepackage{pgfplotstable}
\pgfplotsset{
 my stackbar plot/.style={
             xbar stacked,
             xmin=0,xmax=100,
             symbolic y coords={A,B,C,D,E,F,G},
             ytick=data,
             nodes near coords={xxx},}}

\begin{document}
 \pgfplotstableread[col sep=space]{
 text   --  -    +       ++
 A      0.0 1.7 13.8    84.5
 B      0.0 0.6 20.1    79.3
 C      0.0 1.9 13.2    84.9
 D      0.0 1.6 27.9    70.5
 E      1.3 3.9 19.5    75.3
 F      0.0 1.4 15.0    83.7
 G      0.3 1.7 24.8    73.2
 }\data


\pgfplotstablecreatecol[create col/expr={\thisrow{--}+\thisrow{-}+\thisrow{+}+\thisrow{++}}]{sum}\data %
 \pgfplotstablecreatecol[create col/copy=--]{--o}\data
 \pgfplotstablecreatecol[create col/copy=-]{-o}\data
 \pgfplotstablecreatecol[create col/copy=+]{+o}\data
 \pgfplotstablecreatecol[create col/copy=++]{++o}\data
 \pgfplotstablecreatecol[create col/expr={100/\thisrow{sum}*\thisrow{--o}}]{--}\data
 \pgfplotstablecreatecol[create col/expr={100/\thisrow{sum}*\thisrow{-o}}]{-}\data
 \pgfplotstablecreatecol[create col/expr={100/\thisrow{sum}*\thisrow{+o}}]{+}\data
 \pgfplotstablecreatecol[create col/expr={100/\thisrow{sum}*\thisrow{++o}}]{++}\data
 \pgfplotstablecreatecol[create col/expr={\thisrow{--}+\thisrow{-}+\thisrow{+}+\thisrow{++}}]{sumnew}\data

\pgfplotstabletypeset[columns={text,sum}   ,precision=10,columns/text/.style={string type}]\data \quad
\pgfplotstabletypeset[columns={text,sumnew},precision=10,columns/text/.style={string type}]\data 

%\pgfplotstablesave{\data}{pgfplotstempout.dat}
\begin{tikzpicture}
\begin{axis}[my stackbar plot]
 \addplot table [x expr = \thisrow{--o},y=text] {\data};
 \addplot table [x expr = \thisrow{-o}, y=text] {\data};
 \addplot table [x expr = \thisrow{+o}, y=text] {\data};
 \addplot table [x expr = \thisrow{++o}, y=text] {\data};
\end{axis}
\end{tikzpicture}
\quad
\begin{tikzpicture}
\begin{axis}[my stackbar plot]
 \addplot table [x expr = \thisrow{--},y=text] {\data};
 \addplot table [x expr = \thisrow{-}, y=text] {\data};
 \addplot table [x expr = \thisrow{+}, y=text] {\data};
 \addplot table [x expr = \thisrow{++}, y=text] {\data};
\end{axis}
\end{tikzpicture}

\end{document} 

在此处输入图片描述

答案1

这是一种使用的方法\usepackage{xintexpr}

  • \xinttheiexpr [d] ...\relaxd生成一个小数点后有数字的定点数,其中d是一个数字d =1, 2, ...。它发子弹精确计算的结果。

  • \xinttheexpr trunc(..., d)\relax做同样的事情,但它不是四舍五入,而是截断。(抱歉,对于i舍入和i截断的语法不太清楚,正在发生的事情是有些\xinttheiexpr [d,trunc] ... \relax应该实现,我不知道该选择什么语法,因为我不想让它太冗长,想到了[d↓]......)。

我们可以在允许纯扩展工作的地方特别使用它,就像\xinttheexpr, \xinttheiexprf-expandable 一样。(请参阅xint文档了解其确切含义)。

这里有一些评论,即使经过一些编辑使其不那么冗长,现在也没人能理解,甚至作者自己也无法理解。

在对 的求和中,sumnew我们将 4 个已四舍五入的数字相加。每次(定点)四舍五入最多引入一个绝对误差5 10^-7,因此精确总和的误差最多为2 10^-6 = 0.02 10^-4。如果我们现在将其四舍五入为 4 位数字,则可能存在 的误差0.52 10^-4。这意味着它可能不是精确总和的正确四舍五入,但off by 1对于最后的单位来说S_exact是正确的。我们在这里讨论的是 ,100 (exact sum of the original data)/S_pgfplots其中S_pgfplotspgfplots计算的总和,因此它接近100

如果重新缩放的加数首先被截断为 6 位数字,则其计算总和最多会比4 10^-6=0.04 10^-4实际总和小。如果我们再次将其截断为 4 位数字,off by 1与精确总和的截断相比,我们最多会处于最后一位数字,但好处是知道我们低于精确结果。如果精确结果恰好是100,那么我们几乎可以保证此过程将始终产生结果99.9999100只有当所有比率都精确到 时,它才能产生结果 --- 实际上,如果我们除以 本身恰好 ,6 digits情况就是如此)。sum100

无论如何,这里是代码:

\documentclass{scrreprt}
\usepackage{xintexpr}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\usepackage{pgfplotstable}
\pgfplotsset{
 my stackbar plot/.style={
             xbar stacked,
             xmin=0,xmax=100,
             symbolic y coords={A,B,C,D,E,F,G},
             ytick=data,
             nodes near coords={xxx},}}

\begin{document}
 \pgfplotstableread[col sep=space]{
 text   --  -    +       ++
 A      0.0 1.7 13.8    84.5
 B      0.0 0.6 20.1    79.3
 C      0.0 1.9 13.2    84.9
 D      0.0 1.6 27.9    70.5
 E      1.3 3.9 19.5    75.3
 F      0.0 1.4 15.0    83.7
 G      0.3 1.7 24.8    73.2
 }\data


\pgfplotstablecreatecol[create col/expr={\thisrow{--}+\thisrow{-}+\thisrow{+}+\thisrow{++}}]{sum}\data %
 \pgfplotstablecreatecol[create col/copy=--]{--o}\data
 \pgfplotstablecreatecol[create col/copy=-]{-o}\data
 \pgfplotstablecreatecol[create col/copy=+]{+o}\data
 \pgfplotstablecreatecol[create col/copy=++]{++o}\data
 \pgfplotstablecreatecol[create col/expr={\xinttheiexpr[6]
   100/\thisrow{sum}*\thisrow{--o}\relax}]{--}\data 
 \pgfplotstablecreatecol[create col/expr={\xinttheiexpr[6]
   100/\thisrow{sum}*\thisrow{-o}\relax}]{-}\data 
 \pgfplotstablecreatecol[create col/expr={\xinttheiexpr[6]
   100/\thisrow{sum}*\thisrow{+o}\relax }]{+}\data
 \pgfplotstablecreatecol[create col/expr={\xinttheiexpr[6]
   100/\thisrow{sum}*\thisrow{++o}\relax }]{++}\data 
 \pgfplotstablecreatecol[create col/expr={\xinttheiexpr [6]
 \thisrow{--}+\thisrow{-}+\thisrow{+}+\thisrow{++}\relax}]{sumnew}\data
 % better? or even without [4] to get 100 as rounded integer ?
 % \pgfplotstablecreatecol[create col/expr={\xinttheiexpr[4]
 % \thisrow{--}+\thisrow{-}+\thisrow{+}+\thisrow{++}\relax}]{sumnew}\data

\pgfplotstabletypeset[columns={text,sum}   ,precision=10,columns/text/.style={string type}]\data \quad
\pgfplotstabletypeset[columns={text,sumnew},precision=10,columns/text/.style={string type}]\data 

%\pgfplotstablesave{\data}{pgfplotstempout.dat}
\begin{tikzpicture}
\begin{axis}[my stackbar plot]
 \addplot table [x expr = \thisrow{--o},y=text] {\data};
 \addplot table [x expr = \thisrow{-o}, y=text] {\data};
 \addplot table [x expr = \thisrow{+o}, y=text] {\data};
 \addplot table [x expr = \thisrow{++o}, y=text] {\data};
\end{axis}
\end{tikzpicture}
\quad
\begin{tikzpicture}
\begin{axis}[my stackbar plot]
 \addplot table [x expr = \thisrow{--},y=text] {\data};
 \addplot table [x expr = \thisrow{-}, y=text] {\data};
 \addplot table [x expr = \thisrow{+}, y=text] {\data};
 \addplot table [x expr = \thisrow{++}, y=text] {\data};
\end{axis}
\end{tikzpicture}

\end{document} 

引用

相关内容