![pgfplots: 丸めの問題を修正](https://rvso.com/image/328833/pgfplots%3A%20%E4%B8%B8%E3%82%81%E3%81%AE%E5%95%8F%E9%A1%8C%E3%82%92%E4%BF%AE%E6%AD%A3.png)
xmaxが100に設定されているのに、データの合計が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
\xinttheiexpr [d] ...\relax
は数値 であるd
小数点以下の桁を持つ固定小数点数を生成します。d
d =1, 2, ...
ラウンド正確に計算された結果。\xinttheexpr trunc(..., d)\relax
同じことをしますが、丸めではなく、切り捨てるi
(丸めには があり、i
切り捨てにはがないという疑わしい構文で申し訳ありません。何が起こっているかというと\xinttheiexpr [d,trunc] ... \relax
、いくつかは実装する必要があるということです。冗長になりたくないので、構文として何を選択するかで困っています。考えてみると[d↓]
...)。
これは、特に、\xinttheexpr, \xinttheiexpr
f 展開可能など、純粋な展開によって機能するものが許可されている場所で使用できます。(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_pgfplots
pgfplots
100
再スケールされた加数が最初に 6 桁に切り捨てられた場合、計算された和は4 10^-6=0.04 10^-4
実数と比較して最大で だけ小さくなる可能性があります。これを再度 4 桁に切り捨てると、off by 1
正確な和の切り捨てと比較すると、最後の桁は最大で になりますが、正確な結果より小さいことが分かるという利点があります。正確な結果が正確に である場合100
、この手順で常に が生成されることがほぼ保証されます(すべての比が で正確である場合にのみ99.9999
生成されます--- まあ、実際には、割る 自体が正確に である場合に当てはまります)。100
6 digits
sum
100
とにかく、コードは次のとおりです。
\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}