7

I'm trying to draw a grouped bar plot, but with added dots "on top" to signify outliers in the results.

Currently I have:

    \begin{figure}[]
      \begin{tikzpicture}
        \begin{axis}[
            width  = 1*\textwidth,
            height = 4.5cm,
            major x tick style = transparent,
            ybar=1*\pgflinewidth,
            bar width=13pt,
            symbolic x coords={A,B,C,D},
            xtick = data,
            enlarge x limits=0.25,
            ymax=15,
            ymin=0,
            legend cell align=left,
            legend style={
                    at={(1,1.05)},
                    anchor=south east,
                    column sep=1ex
            }
        ]
            \addplot[style={fill=red,mark=none}]
                coordinates {(A, 4.44) (B,0.1) (C,4.37) (D,4.07)};

            \addplot[style={fill=green,mark=none}]
                coordinates {(A, 0.4) (B,0.8) (C,0.3) (D,0.5)};

            \addplot[style={fill=blue,mark=none}]
                coordinates {(A, 0.2) (B,0) (C,0.9) (D,0.8)};

            \addplot[style={fill=yellow,mark=none}]
                coordinates {(A, 9.59) (B,0.2) (C,8.86) (D,8.62)};

        \draw node[fill,circle,scale=0.5]{} (axis cs:A,7);
        \draw node[fill,circle,scale=0.5]{} (axis cs:B,11);
        \draw node[fill,circle,scale=0.5]{} (axis cs:C,3);
        \draw node[fill,circle,scale=0.5]{} (axis cs:D,12);

        \legend{C1,C2,C3,C4}
      \end{axis}
    \end{tikzpicture}
\end{figure}

This draws the grouped plots etc, but the "dots" always appear at the (0,0) position, ignoring the relative coordinates. See the picture below, where it is close to the "A". Ideally, I'd like to position such a dot above every bar in the graph. How can I properly specify the coordinates?

Above example

  • You're using the \node syntax slightly wrong: It's \node [<options>] at (<coordinate>) {<text};, then your circles will be positioned almost correctly. However, they will appear above the letters A, B, etc., not above a particular bar. Do you want to be able to mark particular bars, or whole groups of bars? – Jake Sep 30 '13 at 17:39
  • Yes, I'd like to put dots above every bar, but only groups would be an acceptable alternative. – KlaasDC Oct 1 '13 at 5:38
5

If you want to add individual data points above specific bars, you can use

\draw (axis cs:A,7) node [xshift=-1.5*\pgfkeysvalueof{/pgf/bar width}, fill,circle,scale=0.5]{};

The red bars would use xshift=-1.5*\pgfkeysvalueof{/pgf/bar width}, the green bars xshift=-0.5*\pgfkeysvalueof{/pgf/bar width}, and so on.

\documentclass{article}
\usepackage{pgfplots, pgfplotstable}
\begin{document}
\pgfplotstableread{
Name C1   C2  C3  C4
A    4.44 0.4 0.2 9.59
B    0.10 0.8 0.0 0.2
C    4.37 0.3 0.9 8.86
D    4.07 0.5 0.8 8.62
}\datatable

\begin{figure}[]
\begin{tikzpicture}
        \begin{axis}[
            width  = 1*\textwidth,
            height = 4.5cm,
            major x tick style = transparent,
            ybar=0,
            bar width=13pt,
            symbolic x coords={A,B,C,D},
            xtick = data,
            enlarge x limits=0.25,
            ymax=15,
            ymin=0,
            legend cell align=left,
            legend style={
                    at={(1,1.05)},
                    anchor=south east,
                    column sep=1ex
            }
        ]
            \addplot[style={fill=red,mark=none}]
                coordinates {(A, 4.44) (B,0.1) (C,4.37) (D,4.07)};

            \addplot[style={fill=green,mark=none}]
                coordinates {(A, 0.4) (B,0.8) (C,0.3) (D,0.5)};

            \addplot[style={fill=blue,mark=none}]
                coordinates {(A, 0.2) (B,0) (C,0.9) (D,0.8)};

            \addplot[style={fill=yellow,mark=none}]
                coordinates {(A, 9.59) (B,0.2) (C,8.86) (D,8.62)};
        \legend{C1,C2,C3,C4}
        \draw (axis cs:A,7) node [xshift=-1.5*\pgfkeysvalueof{/pgf/bar width}, fill,circle,scale=0.5]{} ;
        \draw (axis cs:C,1.5) node [xshift=0.5*\pgfkeysvalueof{/pgf/bar width}, fill,circle,scale=0.5]{} ;
      \end{axis}
    \end{tikzpicture}
\end{figure}
\end{document}

If you only want to highlight particular bars, you can use the nodes near coords functionality, which can be used to place nodes near data points. When providing data using \addplot coordinates (as opposed to using a table), you can simply add [\textbullet] after the coordinates you want to highlight. Note that you'll need to also set point meta=explicit symbolic in the axis options, otherwise nodes near coords creates labels containing the y values of the bars.

Compared to "manually" placing TikZ nodes at the desired locations, this has the advantage of using much less code, and being more easily maintainable because you define the marks together with the data, and don't have to type the coordinate values twice.

\documentclass{article}
\usepackage{pgfplots}
\begin{document}

\begin{figure}[]
\begin{tikzpicture}
        \begin{axis}[
            width  = 1*\textwidth,
            height = 4.5cm,
            major x tick style = transparent,
            ybar=1*\pgflinewidth,
            bar width=13pt,
            symbolic x coords={A,B,C,D},
            xtick = data,
            enlarge x limits=0.25,
            ymax=15,
            ymin=0,
            legend cell align=left,
            legend style={
                    at={(1,1.05)},
                    anchor=south east,
                    column sep=1ex
            },
            nodes near coords,
            point meta=explicit symbolic
        ]
            \addplot[style={fill=red,mark=none}]
                coordinates {(A, 4.44)[\textbullet] (B,0.1) (C,4.37) (D,4.07)};

            \addplot[style={fill=green,mark=none}]
                coordinates {(A, 0.4) (B,0.8) (C,0.3)[\textbullet] (D,0.5)};

            \addplot[style={fill=blue,mark=none}]
                coordinates {(A, 0.2) (B,0) (C,0.9) (D,0.8)};

            \addplot[style={fill=yellow,mark=none}]
                coordinates {(A, 9.59) (B,0.2) (C,8.86) (D,8.62) [\textbullet]};
        \legend{C1,C2,C3,C4}
      \end{axis}
    \end{tikzpicture}
\end{figure}
\end{document}
| improve this answer | |
  • But, how can you precisely specify the dot's position then? This only replaces the text near the bars, right? I'd like to show the highest "outlier" with the dot. – KlaasDC Oct 1 '13 at 6:05
  • @KlaasDC: If you want to place a dot near the yellow "C" bar, you put [\textbullet] after (C,8.86) in the fourth \addplot. Or am I misunderstanding you? – Jake Oct 1 '13 at 6:47
  • But then the dot hovers at a fixed position above the C bar, while I'd like to specify the Y-value of the dot. It's function is similar to an error bar. – KlaasDC Oct 1 '13 at 6:56
  • @KlaasDC: Aaah, now I understand, you're not trying to "highlight" a particular plot, you're trying to add new data points – Jake Oct 1 '13 at 6:56
  • @KlaasDC: I've edited my answer to show how you can add nodes like data points. – Jake Oct 1 '13 at 8:33
2

I'm not sure I understand where it is you want circles exactly, but I'll offer this solution to get the conversation started, since there are no other takers.

This doesn't use tikz and I'm sure a tikz solution is what you would prefer, but in its absence, the \stackinset macro overlays an inset (text or graphics) on an object (text or graphics). I overlaid a few bullets in a fashion I thought might satisfy your need, but please clarify if I missed it. I had to add % to blank lines, since \stackinset is not a long command.

Multiple insets are achieved via nesting, as I show in the MWE. The downside is that you must specify paper (rather than graph) coordinates for the inset location. By using the {c} and {b} arguments, the center-bottom of the inset coordinates are calculated relative to the center-bottom of the image.

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{stackengine}[2013-09-11]
\begin{document}
    \begin{figure}[]
     \stackinset{c}{-3.92cm}{b}{1.52cm}{$\bullet$}{%
     \stackinset{c}{1.22cm}{b}{0.72cm}{$\bullet$}{%
      \begin{tikzpicture}
        \begin{axis}[
            width  = 1*\textwidth,
            height = 4.5cm,
            major x tick style = transparent,
            ybar=1*\pgflinewidth,
            bar width=13pt,
            symbolic x coords={A,B,C,D},
            xtick = data,
            enlarge x limits=0.25,
            ymax=15,
            ymin=0,
            legend cell align=left,
            legend style={
                    at={(1,1.05)},
                    anchor=south east,
                    column sep=1ex
            }
        ]
            \addplot[style={fill=red,mark=none}]
                coordinates {(A, 4.44) (B,0.1) (C,4.37) (D,4.07)};
%
            \addplot[style={fill=green,mark=none}]
                coordinates {(A, 0.4) (B,0.8) (C,0.3) (D,0.5)};
%
            \addplot[style={fill=blue,mark=none}]
                coordinates {(A, 0.2) (B,0) (C,0.9) (D,0.8)};
%
            \addplot[style={fill=yellow,mark=none}]
                coordinates {(A, 9.59) (B,0.2) (C,8.86) (D,8.62)};
%
%        \draw node[fill,circle,scale=0.5]{} (axis cs:A,7);
%        \draw node[fill,circle,scale=0.5]{} (axis cs:B,11);
%        \draw node[fill,circle,scale=0.5]{} (axis cs:C,3);
%        \draw node[fill,circle,scale=0.5]{} (axis cs:D,12);
%
        \legend{C1,C2,C3,C4}
      \end{axis}
    \end{tikzpicture}%
   }}
  \end{figure}
\end{document}

enter image description here

| improve this answer | |
  • That looks exactly how I want it! :) There is really no way to use the graph's coordinates though? For example, could it not be possible to draw a second set of "invisible" bars on top of the original ones, but with dot markers at the values? – KlaasDC Oct 1 '13 at 5:41
  • @KlaasDC I am not a tikz guy, so I'll have to let someone else solve that one. But since no one had contributed a tikz answer, I provided this as a last resort. – Steven B. Segletes Oct 1 '13 at 10:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.