# pgfplots: Clipping Everything Outside a Specific Area

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}
\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,
},
%
]
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:

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:

• I think this is actually a bug: nodes near coords should not generate the last item at all for ybar interval. – Christian Feuersänger Jun 8 '14 at 20:39
• The same is probably true for the missing shift. I noted both on the todo list for pgfplots (i.e. I accept them as bug/feature requests). – Christian Feuersänger Jun 8 '14 at 20:40

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);
}


\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
]
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:

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

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

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


• Thanks. What's the main idea? Some kinf of if-then-else? – Dr. Manuel Kuehner May 29 '14 at 23:20
• Yes, I use a pgfmath if-then-else function with syntax x ? y : z meaning " if x then y else z " – esdd May 30 '14 at 6:51
• Ok. Thanks! (Danke :) I want to wait a bit - maybe another solution is also possible. – Dr. Manuel Kuehner May 30 '14 at 10:55
• No problem, it would be fine if there is another and possible better solution. (In the manual (version 1.10) you can read on page 108: "Currently nodes near coords does not work satisfactorily for ybar interval or xbar interval, sorry.") – esdd May 30 '14 at 11:05
• Didn't see that in the manual - thanks for the hint. – Dr. Manuel Kuehner May 30 '14 at 12:09

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.

Code

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

\usepackage{pgfplots}
\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}
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
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}

• Which version of pgfplots do you have? Your code works for me if I install version 1.8 in my local tree. But it does not work if I use version 1.9 or 1.10 even if I say compat=1.8. – esdd Jun 3 '14 at 8:55
• Indeed, mine is 1.8. – Jesse Jun 3 '14 at 10:24
• That is also the reason why nodes near coords={\pgfmathprintnumber{\pgfkeysvalueof{/data point/y}}} does not work for you. To get the abundances automatically version 1.10 is needed. – esdd Jun 3 '14 at 10:30
• Thanks for the solution. So the key is scope and the clip command?! – Dr. Manuel Kuehner Jun 4 '14 at 8:52
• No, I am afraid not. I did tried it. Further your code does not work for version 1.8. So IMHO there is a backward/forward compatibility between these two versions. I also notice that the other answer requires 1.10 or later. With that informed, I keep two versions. – Jesse Jun 5 '14 at 13:54