# Problem plotting histogram using pgfplots package

The following code plots a histogram using pgfplots.

\documentclass[a4paper]{article}

\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
\centering
\begin{axis}[
ybar,
enlargelimits=0.15,
legend style={at={(0.5,-0.15)},
anchor=north,legend columns=-1},
ylabel={\#percentage},
symbolic x coords={mod2,mod3,mod5,mod7,mod11,mod13,mod17,mod19,mod23},
xtick=data,
nodes near coords,
nodes near coords align={vertical},
]
\addplot coordinates {(mod2,75.4064) (mod3,89.7961) (mod5,94.4597)
(mod7,96.6786) (mod11,97.5600) (mod13,98.2339)
(mod17,98.6138) (mod19,98.9129) (mod23,99.0970)};
\addplot coordinates {(mod2,30.5101) (mod3,34.5384) (mod5,36.3324)
(mod7,37.3570) (mod11,37.9158) (mod13,38.3514)
(mod17,38.6484) (mod19,38.9125) (mod23,39.1067)};
\legend{Residue,non-Residue}
\end{axis}
\end{tikzpicture}

\end{document}

The problem, however, is that the output looks something like this.

Is there a way of spacing the x-axis so that there is no overlap of the ticks and bars on the x-axis?

-

There are a couple of things you can do. The full source code for the examples is at the bottom of this post. Note that you should always specify ymin=0 explicitly, otherwise the lowest data point will be used to determine the extent of the plot.

Make the plot wider: You could use the width and height options to make the plot wide enough to accommodate the x tick labels. To avoid the data labels from overlapping, you can rotate them using every node near coord/.append style={ anchor=mid west, rotate=70 }. In the example below, I've also switched off the upper and right axis borders using axis lines*=left (without the *, the axis lines would have arrow tips), so the rotated labels don't overlap the axis borders. Instead of this, you could also set enlarge y limits={upper,value=0.3} to enlarge the plot in positive y-direction by a factor of 1.3.

Rotate the x tick labels, round the data label values: If you want to keep the format unchanged, you could instead rotate the x tick labels using xticklabel style={ inner sep=0pt, anchor=north east, rotate=45 } (the inner sep and anchor options are needed to get the alignment right); decrease the width of the bars using bar width, and round the data labels to integers using nodes near coords={\pgfmathprintnumber[fixed,precision=0]{\pgfplotspointmeta}}.

Swap the axes: Or you could swap the x and y axes of your coordinates (this would be really simple if you would provide the data as a table, as you could then just redefine which column to use for x and y) and use xbar instead of ybar. This is probably the most sensible approach, as it allows a much better comparison of the values:

Rotated data labels, wide plot

\documentclass[a4paper]{article}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}% <-- moves axis labels near ticklabels (respects tick label widths)

\begin{document}

\begin{tikzpicture}
\centering
\begin{axis}[
ybar,
height=6cm,
width=13cm,
enlarge y limits=false,
axis lines*=left,
ymin=0,
ymax=100,
legend style={at={(0.5,-0.2)},
anchor=north,legend columns=-1},
ylabel={\#percentage},
symbolic x coords={mod2,mod3,mod5,mod7,mod11,mod13,mod17,mod19,mod23},
xtick=data,
nodes near coords,
every node near coord/.append style={
anchor=mid west,
rotate=70
}
]
\addplot coordinates {(mod2,75.4064) (mod3,89.7961) (mod5,94.4597)
(mod7,96.6786) (mod11,97.5600) (mod13,98.2339)
(mod17,98.6138) (mod19,98.9129) (mod23,99.0970)};
\addplot coordinates {(mod2,30.5101) (mod3,34.5384) (mod5,36.3324)
(mod7,37.3570) (mod11,37.9158) (mod13,38.3514)
(mod17,38.6484) (mod19,38.9125) (mod23,39.1067)};
\legend{Residue,non-Residue}
\end{axis}
\end{tikzpicture}
\end{document}

Rotated x labels, node labels rounded to integers:

\documentclass[a4paper]{article}

\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
\centering
\begin{axis}[ybar,
bar width=0.25cm,
ymin=0,
enlarge y limits={upper,value=0.15},
legend style={at={(0.5,-0.25)},
anchor=north,legend columns=-1},
ylabel={\#percentage},
symbolic x coords={mod2,mod3,mod5,mod7,mod11,mod13,mod17,mod19,mod23},
xtick=data,
xticklabel style={
inner sep=0pt,
anchor=north east,
rotate=45
},
nodes near coords={\pgfmathprintnumber[fixed,precision=0]{\pgfplotspointmeta}},
]
\addplot coordinates {(mod2,75.4064) (mod3,89.7961) (mod5,94.4597)
(mod7,96.6786) (mod11,97.5600) (mod13,98.2339)
(mod17,98.6138) (mod19,98.9129) (mod23,99.0970)};
\addplot coordinates {(mod2,30.5101) (mod3,34.5384) (mod5,36.3324)
(mod7,37.3570) (mod11,37.9158) (mod13,38.3514)
(mod17,38.6484) (mod19,38.9125) (mod23,39.1067)};
\legend{Residue,non-Residue}
\end{axis}
\end{tikzpicture}

\end{document}

Swapped x and y axis:

\documentclass[a4paper]{article}

\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}
\centering
\begin{axis}[
xbar,
bar width=0.2cm,
legend style={at={(0.5,-0.15)},
enlarge x limits={upper,value=0.19},
xmin=0,xmax=100,
anchor=north,legend columns=-1},
ylabel={\#percentage},
symbolic y coords={mod2,mod3,mod5,mod7,mod11,mod13,mod17,mod19,mod23},
ytick=data,
nodes near coords,
nodes near coords align=horizontal,
]
\addplot coordinates {(75.4064,mod2) (89.7961,mod3) (94.4597,mod5)
(96.6786,mod7) (97.5600,mod11) (98.2339,mod13)
(98.6138,mod17) (98.9129,mod19) (99.0970,mod23)};
\addplot coordinates {(30.5101,mod2) (34.5384,mod3) (36.3324,mod5)
(37.3570,mod7) (37.9158,mod11) (38.3514,mod13)
(38.6484,mod17) (38.9125,mod19) (39.1067,mod23)};
\legend{Residue,non-Residue}
\end{axis}
\end{tikzpicture}

\end{document}
-
Thanks Jake for your very comprehensive answer. Much appreciated! – Bill Sep 1 '11 at 3:04