pgfplots: corrija problemas de arredondamento

pgfplots: corrija problemas de arredondamento

Tive um problema com o desaparecimento do marcador, pois os dados somavam mais de 100 enquanto xmax estava definido como 100. Consultepgfplots: nó próximo a coordenadas ausentes devido a problemas de arredondamento.

Conforme escrito na resposta à pergunta citada, tentei evitar o problema normalizando o valor para 100. Mas isso levou a erros de arredondamento (muito menores) em linhas anteriormente corretas e agora o marcador desaparece ali. Veja o exemplo a seguir. Antes da normalização a coluna F é afetada, depois da coluna B.

Como posso em umconfiávelmaneira de evitar esse problema de arredondamento? Ou pelo menos receba uma mensagem de erro clara. Eu tenho vários desses gráficos e não quero ter que verificá-los o tempo todo em busca de marcadores ausentes.

\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} 

insira a descrição da imagem aqui

Responder1

Aqui está uma maneira de usar\usepackage{xintexpr}:

  • \xinttheiexpr [d] ...\relaxproduz um número de ponto fixo com ddígitos após a marca decimal, onde dé um número d =1, 2, .... Istorodadaso resultado exatamente calculado.

  • \xinttheexpr trunc(..., d)\relaxfaz o mesmo, mas em vez de arredondar,trunca. (Desculpe pela sintaxe duvidosa com iarredondamento, e não ipor truncar, o que está acontecendo é que alguns \xinttheiexpr [d,trunc] ... \relaxdevem ser implementados, estou confuso com o que escolher como sintaxe porque não quero que seja detalhado, pensei em [d↓]...).

Podemos usar isso em particular em locais onde são permitidas coisas que funcionam por pura expansão, assim \xinttheexpr, \xinttheiexprcomo f-expansíveis. (veja o xintdocumento para saber o que isso significa exatamente).

Aqui estão alguns comentários que ninguém nem mesmo o autor consegue entender agora, mesmo depois de algumas edições para torná-los menos detalhados.

Na soma sumnewestamos adicionando 4 números que foram arredondados. Cada arredondamento (de ponto fixo) introduziu um erro absoluto no máximo 5 10^-7, portanto temos um erro na soma exata que é no máximo 2 10^-6 = 0.02 10^-4. Se arredondarmos agora para 4 dígitos, teremos um possível erro de 0.52 10^-4. O que significa que pode não ser o arredondamento correto da soma exata, mas sim off by 1para a unidade em último lugar. O que S_exactestamos discutindo aqui é 100 (exact sum of the original data)/S_pgfplotsonde S_pgfplotsestá a pgfplotssoma calculada, portanto, está próxima de 100.

Se os somatórios redimensionados fossem primeiro truncados para 6 dígitos, sua soma computada poderia ser menor, no máximo, 4 10^-6=0.04 10^-4em comparação com a soma real. Se truncarmos novamente para 4 dígitos estaremos no máximo off by 1no último dígito em relação ao truncamento da soma exata, mas com a vantagem de saber que estamos abaixo do resultado exato. Se o resultado exato for preciso 100, então temos quase certeza de que esse procedimento sempre produzirá 99.9999(ele só poderia produzir 100se todas as proporções fossem exatas em 6 digits--- bem, na verdade, esse é o caso se o valor sumpelo qual dividimos for exatamente 100).

De qualquer forma, aqui está o 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} 

Bloco de citação

informação relacionada