7

I want to add information to each column of a histogram. every node near coord is probably the best approach. It works well with bar plots but not with the histogram:

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{pgfplots.statistics}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
ybar interval,
xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
% Code to generate labels
nodes near coords={
\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}
},
every node near coord/.style={
anchor=south,xshift=9mm,
},
%
]
\addplot+[hist={bins=3}]
table[row sep=\\,y index=0] {
data\\
1\\ 2\\ 1\\ 5\\ 4\\ 10\\
7\\ 10\\ 9\\ 8\\ 9\\ 9\\
};
\end{axis}
\end{tikzpicture}

\end{document}

I used every node near coord/.style to shift the labels.

The problem is that I have four labels for three columns/bars:

enter image description here

I addition I would like to center the labels. A workaround will be a manual adjustment (every node near coord/.style) just like in the shown example.

Update

Maybe clipping is a possibility. Is there a way to clip the labels (in this case the 7 in the right) away?

Like this:

enter image description here

2 Answers2

6

The necessary xshift for the nodes near coords labels can be calculated from the width of the axis, the number of bins and the value of enlarge x limits (defined in the new macro \enlargexlimits).

nodes near coords*/.add code={}{\tikzset{every node/.append style={xshift={
  (\pgfkeysvalueof{/pgfplots/width}-45pt) % every plot is 45pt smaller then the width
  /(1+2*\enlargexlimits) % correction for enlarge x limits
  /\pgfkeysvalueof{/pgfplots/hist/bins} % number of bins
  /2% shift only half of bin width
}}}},

If you want clipping all stuff right of the plot box you can fill this area with your page color and recalculate the bounding box of the whole plot.

Therefore I define a macro

\newcommand\clipright[1][white]{
  \fill[#1](current axis.south east)rectangle(current axis.north-|current axis.outer east);
  \pgfresetboundingbox
  \useasboundingbox(current axis.outer south west)rectangle(current axis.outer north-|current axis.east);
}

and a second macro to show the resulting boundig box of the plot

\newcommand\showbb{
  \draw[red,dashed](current bounding box.south west)rectangle(current bounding box.north east);
}

enter image description here

\documentclass[margin=5mm]{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=newest} % notice: version 1.10 or later is needed

\newcommand*\enlargexlimits{.1} % default value for enlarge x limits 

\pgfplotsset{%
  hist nodes near coords/.style={%
    nodes near coords*/.add code={}{\tikzset{every node/.append style={xshift={
      (\pgfkeysvalueof{/pgfplots/width}-45pt) % every plot is 45pt smaller then the width
      /(1+2*\enlargexlimits) % correction for enlarge x limits
      /\pgfkeysvalueof{/pgfplots/hist/bins} % number of bins
      /2% shift only half of bin width
    }}}},
    nodes near coords={%
      \pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}
    }}
}

\newcommand\clipright[1][white]{
  \fill[#1](current axis.south east)rectangle(current axis.north-|current axis.outer east);
  \pgfresetboundingbox
  \useasboundingbox(current axis.outer south west)rectangle(current axis.outer north-|current axis.east);
}

\newcommand\showbb{
  \draw[red,dashed](current bounding box.south west)rectangle(current bounding box.north east);
}

\begin{document}

\begin{tikzpicture}

  \begin{axis}[
    ybar interval,
    xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
    enlarge x limits=\enlargexlimits
  ]
    \addplot+[hist={bins=3},hist nodes near coords]
      table[row sep=\\,y index=0] {
      data\\
      1\\ 2\\ 1\\ 5\\ 4\\ 10\\
      7\\ 10\\ 9\\ 8\\ 9\\ 9\\
    };
  \end{axis}
  \clipright
  \showbb
\end{tikzpicture}
\end{document}

But there will be a problem if you increase the number of bins. Here is the result of bin=9:

enter image description here

To solve this you can decrease the enlarge x limits by redefining the macro \enlargexlimits

\begin{tikzpicture}
  \def\enlargexlimits{0.04} % changing the value of `enlarge x limits`
  \begin{axis}[
    ybar interval,
    xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
    enlarge x limits=\enlargexlimits
  ]

Then you will get

enter image description here

Or with \def\enlargexlimits{0} you will get

enter image description here

Note: the labels are again automatically centered.


My former suggestion

To supress the additional label the pgfmath if-then-else function is used. The syntax is x ? y : z meaning " if x then y else z "

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest} % notice: version 1.10 or later is needed

\newcommand*\NNC{\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}}
\newcommand*\enlargexlimits{.1} % default value for enlarge x limits 

\pgfplotsset{%
  hist nodes near coords/.style={%
    nodes near coords*/.add code={}{\tikzset{every node/.append style={xshift={
      (\pgfkeysvalueof{/pgfplots/width}-45pt) % every plot is 45pt smaller then the width
      /(1+2*\enlargexlimits) % correction for enlarge x limits
      /\pgfkeysvalueof{/pgfplots/hist/bins} % number of bins
      /2% shift only half of bin width
    }}}},
    nodes near coords={% 
      \pgfmathparse{
        \pgfkeysvalueof{/data point/x}<#1*\pgfkeysvalueof{/pgfplots/hist/data max}?%
          "\noexpand\NNC"%  if true print nodes near coords
          :% if false suppress the additional node near coords
      }\pgfmathresult%
    }},
  hist nodes near coords/.default={0.9}% if you set data max explicitly it will be 1
}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    ybar interval,
    xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
    enlarge x limits=\enlargexlimits
  ]
    \addplot+[hist={bins=3},hist nodes near coords]
      table[row sep=\\,y index=0] {
      data\\
      1\\ 2\\ 1\\ 5\\ 4\\ 10\\
      7\\ 10\\ 9\\ 8\\ 9\\ 9\\
    };
  \end{axis}
\end{tikzpicture}
\begin{tikzpicture}
  \begin{axis}[
    ybar interval,
    xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
    enlarge x limits=\enlargexlimits
  ]
    \addplot+[hist={bins=2},hist nodes near coords]
      table[row sep=\\,y index=0] {
      data\\
      1\\ 2\\ 1\\ 5\\ 4\\ 10\\
      7\\ 10\\ 9\\ 8\\ 9\\ 9\\
    };
  \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

esdd
  • 85,675
4

An alternative is the use of clip command.

Sine the OP does not provide data point/y infomation, this solution uses home-made substitutes for demonstration purpose. The frame in the sectiond image is again for demonstration whch can be adjusted in the clip command. Remove preaction=draw in the clip option to remove the frame. Note clip=false is required in the solution.

enter image description here

Code

\documentclass[border=10pt,varwidth]{standalone}%{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{pgfplots.statistics}

\begin{document}

Before:

\begin{tikzpicture}
\begin{axis}[
ybar interval,
clip=false,
xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
% Code to generate labels
%nodes near coords={
%\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}
%},
nodes near coords={\pgfmathprintnumber\pgfplotspointmeta\%},
every node near coord/.style={
anchor=south,xshift=9mm,
},
%
]
\begin{scope}
\addplot+[hist={bins=3}]
table[row sep=\\,y index=0] {
data\\
1\\ 2\\ 1\\ 5\\ 4\\ 10\\
7\\ 10\\ 9\\ 8\\ 9\\ 9\\
};
\end{scope}
\end{axis}
\end{tikzpicture}

After:

\begin{tikzpicture}
\begin{axis}[
ybar interval,
clip=false,
xticklabel=\pgfmathprintnumber\tick--\pgfmathprintnumber\nexttick,
% Code to generate labels
%nodes near coords={
%\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}
%},
nodes near coords={\pgfmathprintnumber\pgfplotspointmeta\%},
every node near coord/.style={
anchor=south,xshift=9mm,
},
%
]
\begin{scope}
\clip[preaction=draw] (axis cs: -1,-0.1) rectangle (axis cs:11,8);  % remove preaction=draw to remove the frame
\addplot+[hist={bins=3}]
table[row sep=\\,y index=0] {
data\\
1\\ 2\\ 1\\ 5\\ 4\\ 10\\
7\\ 10\\ 9\\ 8\\ 9\\ 9\\
};
\end{scope}
\end{axis}
\end{tikzpicture}

\end{document}
Jesse
  • 29,686