5

I'm very, very happy with pgfplots and using the ybar-plot-function to create a lot of diagrams. At the moment I wonders if it is possible to mark a missing value, for example with an asterisk. As you can see in the following example, one can easily identify a value of zero, but the missed values are not easy to identify. I would like to mark these empty ybars (in the example at M3, J4, J3) with an asterisk. Does anyone know how to automate or realize that?

\documentclass[
a4paper,%
headings=small,%
]{scrbook}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{pgfplots}
\usepgflibrary{shapes.geometric}
\usetikzlibrary{patterns,arrows}
\pgfplotsset{%
compat=newest,    
every axis legend/.append style={draw=none, font=\scriptsize, column sep=5pt},    
ymajorgrids=true,    
/pgfplots/ybar legend/.style={
/pgfplots/legend image code/.code={%
\draw[##1,/tikz/.cd, bar width=6pt, yshift=-0.25em, bar shift=0pt, xshift=0.8em]
plot coordinates {(0cm,0.8em)};},
},  
/pgfplots/line legend/.style={
/pgfplots/legend image code/.code={%
\draw[mark repeat=2,mark phase=2,##1]
plot coordinates {(0cm,0cm) (0.3cm,0cm)(0.6cm,0cm)};},
}
}

\begin{document}

\begin{figure}[htb]
\centering
\footnotesize

\begin{tikzpicture}
\begin{axis}[
symbolic x coords={M6,M5,J2,M4,M1,M3,J1,M2,J4,J5,J3},
width=15cm,
height=5cm,
ylabel=Prozent,
legend style={at={(0.5,-0.2)}, anchor=north, legend columns=-1},
ybar,
ymin=0,
ymax=100,
enlarge x limits=0.07,
enlarge y limits=0.07
]

\addlegendentry{FS}
\addplot [pattern=north east lines, ybar legend] coordinates {(M6,0) (M5,100) (J2,42.1) (M4,16.7) (M1,0) (M3,100) (J1,100) (M2,100) (J4,) (J5,0) (J3,0)};

\addlegendentry{IS}
\addplot [color=black, fill=lightgray, ybar legend] coordinates {(M6,20) (M5,50) (J2,58.2) (M4,50) (M1,0) (M3,) (J1,100) (M2,100) (J4,100) (J5,100) (J3,)};

\addlegendentry{\=x FS}
\addplot [black, sharp plot, update limits=false, line width = 1pt, line legend] coordinates {(M6,45.9) (J3,45.9)};

\addlegendentry{\=x IS}
\addplot [black, dashed, sharp plot, update limits=false, line width = 1pt, line legend] coordinates {(M6,64.2) (J3,64.2)};

\end{axis}
\end{tikzpicture}

\caption{Variable A: Intersituative Variantenrealisierung}
\end{figure}

\end{document}
2
  • In your real application, will you enter the data by hand (like in your example), or does it come from a datafile? If it is a datafile, what's the format?
    – Jake
    May 27, 2011 at 15:39
  • for the small amounts of data I enter the values manually, these are the diagrams where I need to mark the missing values.
    – MaKa TaBo
    May 27, 2011 at 16:07

1 Answer 1

5

You can do this with a filter point code. I've defined a new style highlight missing data that interprets data points with a value of -1 as missing data and does a bit of work to position a node with an asterisk in the right place before replacing the value with nan, which causes PGFplots not to draw a column for this value. You can change the value to be replaced by calling highlight missing data=<value>, maybe to -9999 or some other value that will definitely not appear in your real data. This code should work independently of the width of the bars or the number of series, but it won't work with horizontal bars at the moment (it could be adjusted to do that, however).

pgfplots ybar chart with asterisks for missing data

\documentclass[
a4paper,%
headings=small,%
]{scrbook}

\usepackage[utf8]{inputenc}
%\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{pgfplots}
\usepgflibrary{shapes.geometric}
\usetikzlibrary{patterns,arrows}
\pgfplotsset{%
compat=newest,    
every axis legend/.append style={draw=none, font=\scriptsize, column sep=5pt},    
ymajorgrids=true,    
/pgfplots/ybar legend/.style={
/pgfplots/legend image code/.code={%
\draw[##1,/tikz/.cd, bar width=6pt, yshift=-0.25em, bar shift=0pt, xshift=0.8em]
plot coordinates {(0cm,0.8em)};},
},  
/pgfplots/line legend/.style={
/pgfplots/legend image code/.code={%
\draw[mark repeat=2,mark phase=2,##1]
plot coordinates {(0cm,0cm) (0.3cm,0cm)(0.6cm,0cm)};},
}
}


% Code needed for highlighting missing data starts here
\makeatletter
\newcommand{\currentplotnumber}{\the\pgfplots@numplots}
\newcommand\numberofbarplots{0}
\makeatother

\pgfkeys{/pgfplots/highlight missing data/.style={
    filter point/.code = {
      \pgfkeys{/pgf/fpu}
      \pgfmathparse{\pgfkeysvalueof{/data point/y}}
      \pgfmathfloattofixed{\pgfmathresult}
      \pgfkeys{/pgf/fpu=false}
      \pgfmathparse{\pgfmathresult==#1}
      \ifnum\pgfmathresult=1
        \pgfkeys{/pgfplots/x coord inv trafo=\pgfkeysvalueof{/data point/x}}
        \let\xposition=\pgfmathresult
        \pgfmathparse{max(\numplotsofactualtype,\numberofbarplots)}
        \global\let\numberofbarplots=\pgfmathresult
        \edef\mystar{
          \noexpand\node at (axis cs:\xposition,0.5) [xshift=-0.5*(2pt+\noexpand\pgfplotbarwidth)*\noexpand\numberofbarplots+1*(\currentplotnumber*(2pt+\noexpand\pgfplotbarwidth)),anchor=base] {*}; % The node with the indicator. 2 pt is the default bar distance. I haven't found a way to read this value dynamically.
        }
        \mystar
        \pgfkeys{/data point/y=nan}
      \else
        \pgfmathparse{\pgfkeysvalueof{/data point/y}}
      \fi
      }      
  },/pgfplots/highlight missing data/.default=-1 % Value indicating missing data
}
% Code for highlighting missing data ends here

\begin{document}

\begin{figure}[htb]
\centering
\footnotesize

\begin{tikzpicture}
\begin{axis}[
symbolic x coords={M6,M5,J2,M4,M1,M3,J1,M2,J4,J5,J3},
width=15cm,
height=5cm,
ylabel=Prozent,
legend style={at={(0.5,-0.2)}, anchor=north, legend columns=-1},
ybar,
bar width=0.3cm,
ymin=0,
ymax=100,
enlarge x limits=0.07,
enlarge y limits=0.07,
highlight missing data
]

\addlegendentry{FS}
\addplot [pattern=north east lines, ybar legend] coordinates {(M6,0) (M5,100) (J2,42.1) (M4,16.7) (M1,0) (M3,100) (J1,100) (M2,100) (J4,-1) (J5,0) (J3,0)};

\addlegendentry{IS}
\addplot [color=black, fill=lightgray, ybar legend] coordinates {(M6,20) (M5,50) (J2,58.2) (M4,50) (M1,0) (M3,-1) (J1,100) (M2,100) (J4,100) (J5,100) (J3,-1)};

\addlegendentry{\=x FS}
\addplot [black, sharp plot, update limits=false, line width = 1pt, line legend] coordinates {(M6,45.9) (J3,45.9)};

\addlegendentry{\=x IS}
\addplot [black, dashed, sharp plot, update limits=false, line width = 1pt, line legend] coordinates {(M6,64.2) (J3,64.2)};

\end{axis}
\end{tikzpicture}

\caption{Variable A: Intersituative Variantenrealisierung}
\end{figure}

\end{document}
2
  • wow, thats excellent!!! thanks very much, jake! that was exactly what I was looking for :-)
    – MaKa TaBo
    May 27, 2011 at 21:39
  • @Matthias: Glad it helps!
    – Jake
    May 27, 2011 at 21:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .