Problema com pgfplots e histogramas

Problema com pgfplots e histogramas

Acabei de brincar com os exemplos binomiais do @Jakes pgfplots dehttps://tex.stackexchange.com/a/198575/4011, no entanto, o histograma parece estar deslocado para a esquerda ou para a direita dependendo de todo o gráfico (veja, por exemplo, o valor k = 50 abaixo). Alguma ideia do que há de errado aqui? Pode ser por causa de erros numéricos do pgfplots? Como corrigi-lo?

\documentclass[tikz,convert]{standalone}

\usepackage{pgfplots}
\usetikzlibrary{patterns}
\pgfplotsset{compat=1.13}


\begin{document}

\begin{tikzpicture}[%
  declare
  function={binom(\k,\n,\p)=
    (\k <= \n)*\n!/(\k!*(\n-\k)!)*\p^\k*(1-\p)^(\n-\k) 
    ;}%
  ]
  \begin{axis}[%
    axis lines=center,%
    ymax=0.25,%
    ymin=0,%
    xmax=60,%
    samples at={0,1,...,50},%
    yticklabel style={%
      /pgf/number format/fixed,%
      /pgf/number format/fixed zerofill,%
      /pgf/number format/precision=1,%
      /pgf/number format/use comma },%
    ybar=0pt,bar width=0.5,%
    xlabel=$k$,%
    ylabel=$B_{n,p}(k)$, minor x tick num=0, ymajorgrids,
    width=15cm, height=6cm]
    \addplot [fill=gray!50, fill opacity=0.5]
    {binom(x,50,0.9)};%
  \end{axis}
\end{tikzpicture}
\begin{tikzpicture}[%
  declare
  function={binom(\k,\n,\p)=
    (\k <= \n)*\n!/(\k!*(\n-\k)!)*\p^\k*(1-\p)^(\n-\k) 
    ;}%
  ]
  \begin{axis}[%
    axis lines=center,%
    ymax=0.25,%
    ymin=0,%
    xmax=60,%
    samples at={0,1,...,50},%
    yticklabel style={%
      /pgf/number format/fixed,%
      /pgf/number format/fixed zerofill,%
      /pgf/number format/precision=1,%
      /pgf/number format/use comma },%
    ybar=0pt,bar width=0.5,%
    xlabel=$k$,%
    ylabel=$B_{n,p}(k)$, minor x tick num=0, ymajorgrids,
    width=15cm, height=6cm]
    \addplot [fill=black, fill opacity=0.5] {binom(x,50,0.7)};%
    \addplot [fill=gray!50, fill opacity=0.5]
    {binom(x,50,0.9)};%
  \end{axis}
\end{tikzpicture}

\begin{tikzpicture}[%
  declare
  function={binom(\k,\n,\p)=
    (\k <= \n)*\n!/(\k!*(\n-\k)!)*\p^\k*(1-\p)^(\n-\k) 
    ;}%
  ]
  \begin{axis}[%
    axis lines=center,%
    ymax=0.25,%
    ymin=0,%
    xmax=60,%
    samples at={0,1,...,50},%
    yticklabel style={%
      /pgf/number format/fixed,%
      /pgf/number format/fixed zerofill,%
      /pgf/number format/precision=1,%
      /pgf/number format/use comma },%
    ybar=0pt,bar width=0.5,%
    xlabel=$k$,%
    ylabel=$B_{n,p}(k)$, minor x tick num=0, ymajorgrids,
    width=15cm, height=6cm]

    \addplot [fill=gray!50, fill opacity=0.5]
    {binom(x,50,0.9)};%
    \addplot [fill=black, fill opacity=0.5] {binom(x,50,0.7)};%
  \end{axis}
\end{tikzpicture}
\end{center}

\end{document}

Saída:

Diagrama 1

Diagrama 2

Diagrama 3

Responder1

Resposta curta: Ao usar ybarnas axisopções, PGFPlots irá deslocar as diferentes séries para evitar barras sobrepostas. Se você quiser que as barras não sejam deslocadas, defina bar shift=0pt.


ybarnas axisopções, série única

Se você usar a ybarchave nas axisopções e plotar apenas uma série, você obterá barras centralizadas nas posições x especificadas:

\begin{axis}[
    ybar,
    ymin=0
]
    \addplot +[samples at={1,...,5}] {x};
\end{axis}


ybarnas axisopções, duas séries

Se você adicionar outra série, o PGFPlots irá deslocar a primeira série para a esquerda e a segunda série para a direita, para que as barras não se sobreponham. Por padrão, há uma 2pt lacuna entre as barras com a mesma coordenada x:

\begin{axis}[
    ybar,
    ymin=0
]
    \addplot +[samples at={1,...,5}] {x};
    \addplot +[samples at={1,...,5}] {5-x};
\end{axis}


ybar=0ptnas axisopções, duas séries

Você pode ajustar a largura do intervalo entre as séries usando o argumento opcional para o ybarestilo nas axisopções. Se você definir ybar=0pt, as barras ficarão alinhadas umas com as outras:

\begin{axis}[
    ybar=0pt,
    ymin=0
]
    \addplot +[samples at={1,...,5}] {x};
    \addplot +[samples at={1,...,5}] {5-x};
\end{axis}


ybar, bar shift=0ptnas axisopções, duas séries

Se não quiser que as barras sejam deslocadas em direções diferentes, você pode definir bar shift=0pt. Dessa forma, barras com a mesma coordenada x serão desenhadas no mesmo local, levando a barras sobrepostas:

\begin{axis}[
    ybar,
    bar shift=0pt,
    ymin=0
]
    \addplot +[samples at={1,...,5}] {x};
    \addplot +[samples at={1,...,5}] {5-x};
\end{axis}

No manual do PGFPlots diz que bar shift"configura um shift para xbare ybar", e que o valor padrão para este estilo é 0pt. Por que então você obtém resultados diferentes ao incluir ou omitir bar shift=0pt? Isso ocorre porque chamar ybaras axisopções sobrescreve o valor padrão bar shifte o substitui por uma expressão matemática:

/pgf/bar shift={%
        % total width = n*w + (n-1)*skip
        % -> subtract half for centering
        -0.5*(\numplotsofactualtype*\pgfplotbarwidth + (\numplotsofactualtype-1)*(#1))  + 
        % the '0.5*w' is for centering
        (.5+\plotnumofactualtype)*\pgfplotbarwidth + \plotnumofactualtype*(#1)}

Essa expressão leva ao deslocamento que vimos nos exemplos 2 e 3. O #1parâmetro é o intervalo entre as barras ( 2ptpor padrão).


ybarnas \addplotopções, bar shift=5ptnas axisopções, duas séries

Você pode verificar se o valor padrão para bar shifté de fato, como diz o manual, 0ptmovendo a ybarchave das axisopções para as \addplotopções e definindo um valor diferente para bar shiftnas axisopções. Agora todas as barras são deslocadas para a direita por 5pt:

\begin{axis}[
    bar shift=5pt,
    ymin=0
]
    \addplot +[ybar, mark=none, fill=blue!30!white, samples at={1,...,5}] {x};
    \addplot +[ybar, mark=none, fill=red!30!white, samples at={1,...,5}] {5-x};
\end{axis}

informação relacionada