pgfplots: corregir problemas de redondeo

pgfplots: corregir problemas de redondeo

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} 

ingrese la descripción de la imagen aquí

Respuesta1

Aquí hay una manera de usar\usepackage{xintexpr}:

  • \xinttheiexpr [d] ...\relaxproduce un número de coma fija con ddígitos después de la marca decimal, donde des un número d =1, 2, .... Élrondasel resultado calculado exactamente.

  • \xinttheexpr trunc(..., d)\relaxhace lo mismo pero en lugar de redondear,trunca. (Perdón por la sintaxis dudosa con iel redondeo, y no ipor el truncamiento, lo que está sucediendo es que algunas \xinttheiexpr [d,trunc] ... \relaxdeberí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, \xinttheiexprlo son las f-expandibles. (consulte el xintdocumento 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 sumnewestamos 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 1de la unidad que está en último lugar. Lo que S_exactestamos discutiendo aquí es 100 (exact sum of the original data)/S_pgfplotsdonde S_pgfplotsestá la pgfplotssuma 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^-4comparación con la real. Si truncamos eso a 4 dígitos nuevamente estamos como máximo off by 1en 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 100solo si todas las proporciones fueran exactas en 6 digits--- bueno, en realidad ese es el caso si el resultado sumpor 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} 

cita en bloque

información relacionada