![pgfplots: Rundungsprobleme korrigieren](https://rvso.com/image/328833/pgfplots%3A%20Rundungsprobleme%20korrigieren.png)
Ich hatte ein Problem mit verschwindenden Markern, da die Datensumme mehr als 100 betrug, während xmax auf 100 eingestellt war. Siehepgfplots: Knoten in der Nähe der Koordinaten fehlt aufgrund von Rundungsproblemen.
Wie in der Antwort auf die zitierte Frage geschrieben, habe ich versucht, das Problem zu umgehen, indem ich den Wert auf 100 normalisiert habe. Dies führte jedoch zu (viel kleineren) Rundungsfehlern in vorher korrekten Zeilen und nun verschwinden dort die Markierungen. Siehe das folgende Beispiel. Vor der Normalisierung ist die Spalte F betroffen, danach die Spalte B.
Wie kann ich in einemzuverlässigWie kann man dieses Rundungsproblem vermeiden? Oder zumindest eine klare Fehlermeldung erhalten. Ich habe eine ganze Reihe dieser Diagramme und möchte sie nicht ständig auf fehlende Markierungen überprüfen müssen.
\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}
Antwort1
Hier ist eine Möglichkeit,\usepackage{xintexpr}
:
\xinttheiexpr [d] ...\relax
erzeugt eine Festkommazahl mitd
Ziffern nach dem Dezimalzeichen, wobeid
eine Zahl istd =1, 2, ...
. EsRundendas exakt berechnete Ergebnis.\xinttheexpr trunc(..., d)\relax
macht das gleiche, aber anstatt zu runden,kürzt. (Entschuldigen Sie die zweifelhafte Syntax bezüglichi
des Rundens und nichti
des Abschneidens. Was passiert ist, dass einige\xinttheiexpr [d,trunc] ... \relax
implementiert werden sollten. Ich bin ratlos, welche Syntax ich wählen soll, weil ich nicht möchte, dass es zu ausführlich wird. Habe darüber nachgedacht[d↓]
…).
Wir können dies insbesondere an Stellen verwenden, an denen Dinge zulässig sind, die durch reine Erweiterung funktionieren, wie \xinttheexpr, \xinttheiexpr
z. B. f-expandable. ( xint
Was das genau bedeutet, erfahren Sie in der Dokumentation.)
Hier sind einige Kommentare, die selbst nach einigen Bearbeitungen, um sie weniger wortreich zu machen, niemand mehr verstehen kann, nicht einmal der Autor.
In der Summe für sumnew
addieren wir 4 Zahlen, die gerundet wurden. Jede (Festkomma-)Rundung führte zu einem absoluten Fehler von höchstens 5 10^-7
, daher haben wir einen Fehler in der exakten Summe von höchstens 2 10^-6 = 0.02 10^-4
. Wenn wir das jetzt auf 4 Ziffern runden, haben wir einen möglichen Fehler von 0.52 10^-4
. Das bedeutet, dass es sich möglicherweise nicht um die korrekte Rundung der exakten Summe handelt, sondern off by 1
um die Einheit an der letzten Stelle. Das, was S_exact
wir hier diskutieren, ist , 100 (exact sum of the original data)/S_pgfplots
wobei S_pgfplots
die berechnete Summe ist pgfplots
, daher liegt sie nahe bei 100
.
Wenn die neu skalierten Summanden zuerst auf 6 Ziffern gekürzt würden, könnte ihre berechnete Summe im 4 10^-6=0.04 10^-4
Vergleich zur tatsächlichen um höchstens kleiner sein. Wenn wir das wieder auf 4 Ziffern kürzen, sind wir off by 1
im Vergleich zur Kürzung der exakten Summe höchstens bei der letzten Ziffer, haben aber den Vorteil, dass wir wissen, dass wir unter dem exakten Ergebnis liegen. Wenn das exakte Ergebnis genau ist 100
, dann ist uns fast garantiert, dass dieses Verfahren immer ergibt 99.9999
(es könnte 100
nur ergeben, wenn alle Verhältnisse bei genau wären 6 digits
– nun, eigentlich ist das der Fall, wenn die, sum
durch die wir dividieren, selbst genau ist 100
).
Wie dem auch sei, hier ist der Code:
\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}