3

I have been trying to figure out how to draw on top of bars to put tick marks on each bar, but I can't seem to figure out how to draw on top of the bar. Here's the minimal example:

\documentclass{standalone}
\usepackage{pgfplots}

\definecolor{bluethree}{cmyk}{0.83,0.27,0,0.22}

\begin{document}
\begin{tikzpicture}
    \begin{axis}[width  = \textwidth,
    axis on top,
    ybar stacked,
    bar width=14pt,
    xticklabels = {A,B,C,D,E},
    xtick = {1,...,5},
    enlarge x limits=0.1,
    axis line style={-},
    ymin=-0,ymax=70,
    x=4cm,
    axis line style = thick,
    ytick align = outside
    ]

    \addplot[style={bluethree!90!black,fill=bluethree!80,mark=none}]
    coordinates {(1, 33.74) (2, 32.43) (3, 20.52) (4, 26.83) (5, 31.33)}; 

    \addplot[style={bluethree!90!black,fill=bluethree!40,mark=none}]
    coordinates {(1, 14.74) (2, 7.43) (3, 29.07) (4, 22.44) (5,13.60)}; 

    \draw[thick, black] (axis cs: 1,5) -- (axis cs: 0.8,5);

    \end{axis}
\end{tikzpicture}
\end{document}

If you see, the line I draw at the end with \draw[thick, black] (axis cs: 1,5) -- (axis cs: 0.8,5); draws the line starting at the left most of the bar, instead of right on the middle and above it. My end goal is to have something like this for each bar (i.e. divide each bar in equal parts, in this example, bar A has tick marks at 25, 50, and 75% of its height).

enter image description here

2

This is because "stacked" plots are drawn in reverse order by default. The PGFPlots manual (v1.15) states in section 4.5.9 as description to the key reverse stacked plots=true|false

Configures the sequence in which stacked plots are drawn. This is more or less a technical detail which should not be changed in any normal case.
The motivation is as follows: suppose multiple \addplot commands are stacked on top of each other and they are processed in the order of appearance. Then, the second plot could easily draw its lines (or fill area) on top of the first one { hiding its marker or line completely. Therefor, pgfplots reverses the sequence of drawing commands.
This has the side-effect that any normal TikZ paths inside of an axis will also be processed in reverse sequence.

Thus, you could state reverse stacked plots=false in the axis options, but a better solution most likely is to move the \draw command(s) before the \addplot commands.

% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \pgfplotsset{
        % use this `compat' level of higher so TikZ coordinates don't have to be
        % prefixed by `axis cs:'
        compat=1.11,
    }
    \definecolor{bluethree}{cmyk}{0.83,0.27,0,0.22}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        axis on top,
        ybar stacked,
        bar width=14pt,
        xticklabels={A,B,C,D,E},
        xtick={1,...,5},
        enlarge x limits=0.1,
        ymin=-0,ymax=70,
        axis line style=thick,
        ytick align=outside,
    ]

        % moved this command *before* the `\addplot's
        % (if you use `\pgfplotbarwidth', i.e. a command storing a *length*,
        %  also the other coordinate has to be a length ...
        \draw [thick, black] (axis cs:1,5) -- +(\pgfplotbarwidth/2,0pt);
        %  ... otherwise both are interpreted as axis coordinates as in the
        %  following command)
        % \draw [thick, black] (axis cs:2,10) -- +(\pgfplotbarwidth/2,0);

        \addplot [bluethree!90!black,fill=bluethree!80]
            coordinates {(1, 33.74) (2, 32.43) (3, 20.52) (4, 26.83) (5, 31.33)};

        \addplot [bluethree!90!black,fill=bluethree!40]
            coordinates {(1, 14.74) (2, 7.43) (3, 29.07) (4, 22.44) (5,13.60)};

    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

  • Quite simple fix. However, I thought I could use \draw[thick, black] (1,5) -- +(\pgfplotbarwidth/2,0); to draw a horizontal line from the middle of the bar to the right edge, but this doesn't seem to work. Am I missing something obvious again? I'll open another question if necessary. – ralk912 Mar 1 '18 at 18:45
  • @ralk912, no, this was introduced by compat=1.11. See my edited answer. – Stefan Pinnow Mar 1 '18 at 19:13
  • Very nice. It works well. As an added comment I had to manually adjust for the line thickness (adding a \draw [thick, black] (axis cs:1,5) -- +(\pgfplotbarwidth/2-0.2pt,0);), which is not a problem in my case but I thought I'd leave it here in case its helpful for someone else. – ralk912 Mar 1 '18 at 19:22
  • I've been playing with this a bit, but I can't seem to figure out how to have the line across the bar. I tried \draw [thick, black] (axis cs:1-\pgfplotbarwidth/2+0.2pt,5) -- +(\pgfplotbarwidth/2-0.2pt,0), but of course I can't use pt values in axis cs, can I? – ralk912 Mar 2 '18 at 19:23
  • Sorry, but I am not 100$ sure what you finally want to achieve. But in general you cannot mix axis cs: and "canvas cs:" in one "normal coordinate". But if you load TikZ's calc library you could state a coordinate like ($ (axis cs:1,5) - (\pgfplotbarwidth/2-0.2pt,0pt) $). Does that help to solve your problem? – Stefan Pinnow Mar 2 '18 at 20:44
2

One possibility is to store the nodes on top of the bars using this answer, and to draw the annotations after \end{axis}.

\documentclass{standalone}
\usepackage{pgfplots}
\usetikzlibrary{decorations.pathreplacing,decorations.markings}

\definecolor{bluethree}{cmyk}{0.83,0.27,0,0.22}
\pgfplotsset{% from https://tex.stackexchange.com/a/287528/121799
    name nodes near coords/.style={
        every node near coord/.append style={
            name=#1-\coordindex,
            alias=#1-last,
        },
    },
    name nodes near coords/.default=coordnode
}
\tikzset{mymarks/.style={decorate,   decoration={markings,mark=at position .25 with {\draw[thick] (0pt,-4pt) --
   (0pt,4pt);},mark=at position .5 with {\draw[thick] (0pt,-4pt) -- (0pt,4pt);},
   mark=at position .75 with {\draw[thick] (0pt,-4pt) -- (0pt,4pt);}
   }}}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[width  = \textwidth,
    axis on top,
    ybar stacked,
    bar width=14pt,
    xticklabels = {A,B,C,D,E},
    xtick = {1,...,5},
    enlarge x limits=0.1,
    axis line style={-},
    ymin=-0,ymax=70,
    x=4cm,
    axis line style = thick,
    ytick align = outside,
    nodes near coords={},
    nodes near coords align={anchor=south}
    ]

    \addplot[style={bluethree!90!black,fill=bluethree!80,mark=none}]
    coordinates {(1, 33.74) (2, 32.43) (3, 20.52) (4, 26.83) (5, 31.33)}; 

    \addplot[name nodes near coords=myname,style={bluethree!90!black,fill=bluethree!40,mark=none}]
    coordinates {(1, 14.74) (2, 7.43) (3, 29.07) (4, 22.44) (5,13.60)}; 
    %\draw[thick, black] (axis cs: 1,5) -- (axis cs: 0.8,5);
    \coordinate (O) at (axis cs:0,0);
    \end{axis}
    \foreach \i in {0,...,4}{
    \draw[mymarks] (myname-\i.south east) -- (O-|myname-\i.south east);}
\end{tikzpicture}
\end{document}

enter image description here

It will be possible to refine this (here the number of annotations is hardcoded) if this turns out the direction you want to go .

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.