[Tex/LaTex] Fill the area determined by two pgfplots graphs

pgfplotstechnical-drawingtikz-pgf

I need to fill the region determined by two (Gaussian) curves and the right red line (the region is brushed in green in the figure below). I also wonder what is the best way to draw vertical line which goes through the intersection of both graphs (the left red line on the figure).

Any pointers would be greatly appreciated.

bayes_error

My initial attemt is pasted below.

\documentclass{standalone}
\usepackage{pgfplots}

\begin{document}

\pgfmathdeclarefunction{dnorm}{2}{%
  \pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{tikzpicture}
\begin{axis}[domain=0:12, samples=100, height=5cm, width=10cm]
% Fill aread under the curves
\addplot [fill=red!20, draw=none, domain=0:6] {dnorm(6.5,1.5)} \closedcycle;
\addplot [fill=blue!20, draw=none, domain=6:10] {dnorm(4,1)} \closedcycle;
% Draw curves
\addplot [thick] {dnorm(4,1)};
\addplot [thick] {dnorm(6.5,1.5)};
\end{axis}
\end{tikzpicture}

\end{document}

My solution

A picture is worth a thousand words. Code is pasted below.
bayes_error

\documentclass{article}
\usepackage{tkz-fct}
\usetikzlibrary{intersections}

\begin{document}

\tikzset{
   name plot/.style={every path/.style={name path global=#1}}
}

% Extract coordinates for point X
\makeatletter
\newcommand{\gettikzxy}[3]{%
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
\makeatother

% Dimlines
\def\Dimline[#1][#2][#3][#4]{
\begin{scope}[thin, >=stealth'] % redefine as flechas
\draw let \p1=#1, \p2=#2, \n0={veclen(\x2-\x1,\y2-\y1)} in [|<->|,
decoration={markings,mark=at position .5 with {\node[#3] at (0,0)
{#4};},
},
postaction=decorate] #1 -- #2 ;
\end{scope}
}

\begin{tikzpicture}[scale=1,font=\small]
\tkzInit[xmin=0,xmax=12,ymin=0,ymax=.3,ystep=.05]
% Draw coordinates
\draw[>=stealth', <->] (0,6) node[above] {$y$} -- (0,0) --  (12.5,0) node[right] {$x$};
% Draw functions and areas
\tkzFct[name plot=A,thick,color=red,domain=0:12]{1/(1.5*sqrt(2*pi))*exp(-((x-4.5)**2)/(2*1.5**1))}
\tkzDrawArea[opacity=.3,color=blue,domain = 7:12]
\tkzFct[name plot=B,thick,color=blue,domain=0:12]{1/(2*sqrt(2*pi))*exp(-((x-7)**2)/(2*2**1))}
\tkzDrawArea[opacity=.3,color=red,domain=0:7]
\tkzDrawAreafg[between=b and a,opacity=.3,color=green,domain = 0:7]
% Intersection between curves
\path [name intersections={of=A and B,by=C}];
% Extract coordinates of C
\gettikzxy{(C)}{\cx}{\cy}
% Vertical lines
\draw [thick,dashed, black] (\cx,0) -- (\cx,5.5) node [above] {$x_{0}$};
\draw [thick,dashed, black] (7,0) -- (7,5.5) node [above] {$\hat{x}$};
% Define regions
\Dimline[($(0,0)+(0,-.6)$)][($(7,0)+(0,-.6)$)][above,black][$\mathcal{R}_{1}$];
\Dimline[($(7,0)+(0,-.6)$)][($(12,0)+(0,-.6)$)][above, black][$\mathcal{R}_{2}$];
\end{tikzpicture}

\end{document}

Best Answer

Since PGFPlots version 1.10 came out, there's a much more elegant way to do this. See Christian Feuersänger's answer.


For pre-1.10 versions of PGFPlots:

You can fill the areas above a curve f and below a curve g by first plotting f and then stacking min(g-f, 0) on top. That expression will become 0 whenever f<=g, and g-f whenever f>g.

To get the vertical lines, you can use the intersections approach from How do I name a plot in tikz and use it for intersections? together with How can I add a zero line to a plot?

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{intersections}

\begin{document}

\pgfmathdeclarefunction{dnorm}{2}{%
  \pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{tikzpicture}
\begin{axis}[
    domain=0:12,
    samples=101,
    height=5cm,
    width=10cm
]

% Fill aread under both curves, start stacking
\addplot [
    fill=yellow,
    draw=none,
    domain=0:6,
    stack plots=y
] {min(dnorm(4,1),dnorm(6.5,1.5)) } \closedcycle;

% Stack difference between two curves on top, but only where the second curve is higher
\addplot [
    fill=orange,
    draw=none,
    domain=0:6,
    stack plots=y
] {max( dnorm(6.5,1.5) - dnorm(4,1),0)} \closedcycle;

% Fill tail of first curve (without stacking)
\addplot [
    fill=cyan,
    draw=none,
    domain=6:12
] {dnorm(4,1)} \closedcycle;


% Draw curves
\addplot [thin, smooth, name path global=first] {dnorm(4,1)};
\addplot [thin, smooth, name path global=second] {dnorm(6.5,1.5)};

% Draw vertical line:
\draw [red, thick] ({rel axis cs:0,0}-|{axis cs:6,0}) -- ({rel axis cs:0,1}-|{axis cs:6,0});
\draw [red, thick, name intersections={of={first and second}}] ({rel axis cs:0,0}-|intersection-1) -- ({rel axis cs:0,1}-|intersection-1);
\end{axis}
\end{tikzpicture}

\end{document}