# Custom data labels for each plot in bar chart

I have a simple bar chart, but I want the data labels to have a custom string value. For example, see the attached picture. I have found plenty of examples with plots, but nothing for bar charts. Note that every single co-ordinate has a different value associated with it. Is there a way I can enter a custom value, as some sort of additional argument to the coordinates?

\begin{figure}
\begin{tikzpicture}
\begin{axis}[
ybar,
enlargelimits=0.15,
legend style={at={(0.5,-0.15)},
anchor=north,legend columns=-1},
ylabel={Speedup},
xlabel={\# of Model Elements (millions)},
symbolic x coords={1m,1.5m,2m,4m},
xtick=data,
nodes near coords,
nodes near coords align={vertical},
]
\addplot coordinates {(1m,92.021) (1.5m,235.809) (2m,276.824) (4m,340.847)};
\end{axis}
\end{tikzpicture}
\caption{Results}
\label{fig:mycaption}
\end{figure}


This is very easy: just build up a list of strings and access them with \coordindex. To this end we define a comma-separated list of strings,

\edef\mylst{"An arbitrary string","String","Custom label","Not this data"}


where the first entry (which has internally index 0) will be used for the first node, the second entry for the second node, and so on. Make sure that the list as at least as many entries as nodes that exist.

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\begin{document}
\begin{figure}
\begin{tikzpicture}
\edef\mylst{"An arbitrary string","String","Custom label","Not this data"}
\begin{axis}[width=12cm,
ybar,
enlargelimits=0.15,
legend style={at={(0.5,-0.15)},
anchor=north,legend columns=-1},
ylabel={Speedup},
xlabel={\# of Model Elements (millions)},
symbolic x coords={1m,1.5m,2m,4m},
xtick=data,
nodes near coords=\pgfmathsetmacro{\mystring}{{\mylst}[\coordindex]}\mystring,
nodes near coords align={vertical},
]
\addplot coordinates {(1m,92.021) (1.5m,235.809) (2m,276.824) (4m,340.847)};
\end{axis}
\end{tikzpicture}
\caption{Results}
\label{fig:mycaption}
\end{figure}
\end{document}


The strings are a bit too long. Are you OK with using multiple lines for them?

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\begin{document}
\begin{figure}[htb]
\centering
\begin{tikzpicture}
\edef\mylst{"An arbitrary string","String","Custom label","Not this data"}
\begin{axis}[ymax=370,
ybar,
enlargelimits=0.15,
legend style={at={(0.5,-0.15)},
anchor=north,legend columns=-1},
ylabel={Speedup},
xlabel={\# of Model Elements (millions)},
symbolic x coords={1m,1.5m,2m,4m},
xtick=data,
nodes near coords style={font=\sffamily,align=center,text width=4em},
nodes near coords=\pgfmathsetmacro{\mystring}{{\mylst}[\coordindex]}\mystring,
nodes near coords align={vertical},
]
\addplot coordinates {(1m,92.021) (1.5m,235.809) (2m,276.824) (4m,340.847)};
\end{axis}
\end{tikzpicture}
\caption{Results}
\label{fig:mycaption}
\end{figure}
\end{document}


• Excellent, thank you! Can you explain what the \mystring does? – Sina Madani Feb 11 at 17:25
• @SinaMadini This is a comma-separated list of strings that gets used in the nodes near coords. – user194703 Feb 11 at 17:30
• It seems to be only using the first character of the string, Is this a limitation of the command? – Sina Madani Feb 11 at 17:37
• @SinaMadani I added the screen shot, and as you see there are the full strings. If you only see the first character, this can have many reasons, one of them being is that you load the babel package. In that case you need to load \usetikzlibrary{babel}. If this does not work, add a full compilable minimal working example to your question, my answer works. – user194703 Feb 11 at 17:39
• Thanks, it seems to be working now. I was trying it with a minimal graph using a single plot, but with multiple plots it works. – Sina Madani Feb 11 at 17:49

I found one solution which seems to work (adapted from this answer):

After the \addplot, type e.g. \node [above] at (axis cs: 1m, 92.021) {an arbitrary string};

Also need to remove the nodes near coords option to remove the existing (default) data label.

• Of course you can do this, but this would be a "100% manual solution". By that I mean that, whenever you change something in your data, you would also have to adjust the "manual" \nodes. – Stefan Pinnow Mar 10 at 16:23

A straightforward way of doint this would be to provide a table (instead of coordinates) and add another column with the stuff you want to show in the nodes near coords.

For details please have a look at the comments in the code.

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{
% use this compat level or higher to make use of the "advanced" axis
% label placement
compat=1.3,
}
% instead of stating the coordinates directly store them in a data file/table
\begin{filecontents*}{MyData.txt}
x       y       label
1m      92.021  {An \\ arbitrary \\ string}
1.5m    235.809 String
2m      276.824 {custom label}
4m      340.847 {not this data}
\end{filecontents*}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
ybar,
enlargelimits=0.15,
ylabel={Speedup},
xlabel={\# of Model Elements (millions)},
% place xticks at data points (of the first \addplot)
xtick=data,
% label the xticks with data from the table
xticklabels from table={MyData.txt}{x},
% add nodes to the coordinates
nodes near coords,
% the nodes contain non-numeric data
point meta=explicit symbolic,
% if line breaks are included in the strings, align must be set/used
nodes near coords style={
align=center,
%            % (alternatively of giving line breaks manually to the labels you
%            %  could give a fixed with of the label nodes)
%            text width=5em,
},
]
% simply use the coordinate index as x value
% (the label is then used from xticklabels from table)
x expr=\coordindex,
% use y coordinate from table column with header "y"
y=y,
% use column with header "label" for the nodes near coords label
meta=label,
] {MyData.txt};
\end{axis}
\end{tikzpicture}
\end{document}