![pgfplots: corregir problemas de redondeo](https://rvso.com/image/328833/pgfplots%3A%20corregir%20problemas%20de%20redondeo.png)
Tuve un problema con la desaparición del marcador ya que los datos suman más de 100 mientras xmax estaba establecido en 100. Consultepgfplots: falta el nodo cerca de las coordenadas debido a problemas de redondeo.
Como está escrito en la respuesta a la pregunta citada, traté de evitar el problema normalizando el valor a 100. Pero esto condujo a errores de redondeo (mucho más pequeños) en filas previamente correctas y ahora el marcador desaparece allí. Vea el siguiente ejemplo. Antes de la normalización la columna F se ve afectada, después la columna B.
¿Cómo puedo en unconfiable¿Cómo evitar este problema de redondeo? O al menos recibir un mensaje de error claro. Tengo bastantes de estos gráficos y no quiero tener que revisarlos todo el tiempo para ver si faltan marcadores.
\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}
Respuesta1
Aquí hay una manera de usar\usepackage{xintexpr}
:
\xinttheiexpr [d] ...\relax
produce un número de coma fija cond
dígitos después de la marca decimal, donded
es un númerod =1, 2, ...
. Élrondasel resultado calculado exactamente.\xinttheexpr trunc(..., d)\relax
hace lo mismo pero en lugar de redondear,trunca. (Perdón por la sintaxis dudosa coni
el redondeo, y noi
por el truncamiento, lo que está sucediendo es que algunas\xinttheiexpr [d,trunc] ... \relax
deberían implementarse, estoy bloqueado por qué elegir como sintaxis porque no quiero que sea detallado, pensé en[d↓]
...).
Podemos usar esto en particular en lugares donde se permite que las cosas funcionen por pura expansión, como \xinttheexpr, \xinttheiexpr
lo son las f-expandibles. (consulte el xint
documento para saber qué significa eso exactamente).
Aquí hay algunos comentarios que nadie, ni siquiera el autor, puede entender ahora, incluso después de algunas modificaciones para hacerlos menos detallados.
En la sumatoria sumnew
estamos sumando 4 números que han sido redondeados. Cada redondeo (de punto fijo) introdujo un error absoluto como máximo 5 10^-7
, por lo que tenemos un error en la suma exacta que es como máximo 2 10^-6 = 0.02 10^-4
. Si redondeamos eso ahora a 4 dígitos, tenemos un posible error de 0.52 10^-4
. Lo que significa que puede que no sea el redondeo correcto de la suma exacta, sino off by 1
de la unidad que está en último lugar. Lo que S_exact
estamos discutiendo aquí es 100 (exact sum of the original data)/S_pgfplots
donde S_pgfplots
está la pgfplots
suma calculada, por lo tanto, está cerca de 100
.
Si los sumandos reescalados se truncaran primero a 6 dígitos, su suma calculada podría ser como máximo menor en 4 10^-6=0.04 10^-4
comparación con la real. Si truncamos eso a 4 dígitos nuevamente estamos como máximo off by 1
en el último dígito en comparación con el truncamiento de la suma exacta, pero con la ventaja de saber que estamos por debajo del resultado exacto. Si el resultado exacto es exactamente 100
, entonces tenemos casi la garantía de que este procedimiento siempre producirá 99.9999
(podría producir 100
solo si todas las proporciones fueran exactas en 6 digits
--- bueno, en realidad ese es el caso si el resultado sum
por el que dividimos es exactamente 100
).
De todos modos, aquí está el código:
\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}