28

This graphic is a typical representation of the problem of heteroskedasticity in a model of linear regression. If someone could guide me on how to do with tikz , I would be very grateful.

Regards

  • 3
    Very related: Plotting Population Regression Function with pgfplot – Jake Jul 9 '15 at 12:05
  • Certainly very similar. Thank You. Although a representation in three dimensions is much more elegant. – Héctor Garrido Jul 9 '15 at 12:08
  • You right @Héctor that this representation in three dimensions is much more elegant and informative. I'm also after this graph. Good Luck. – MYaseen208 Jul 9 '15 at 12:23
42

Here's one approach using PGFPlots, based on the 2D version found at Plotting Population Regression Function with pgfplot

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\begin{document}

\begin{tikzpicture}[ % Define Normal Probability Function
declare function={
            normal(\x,\m,\s) = 1/(2*\s*sqrt(pi))*exp(-(\x-\m)^2/(2*\s^2));
        }
       ]
\begin{axis}[
    no markers,
    domain=0:12,
    zmin=0, zmax=1,
    xmin=0, xmax=3,
    samples=200,
   samples y=0,
    axis lines=middle,
    xtick={0.5,1.5,2.5},
    xmajorgrids,
    xticklabels={},
    ytick=\empty,
    xticklabels={$x_1$, $x_2$, $x_3$},
    ztick=\empty,
    xlabel=$x$, xlabel style={at={(rel axis cs:1,0,0)}, anchor=west},
    ylabel=$y$, ylabel style={at={(rel axis cs:0,1,0)}, anchor=south west},
    zlabel=Probability density, zlabel style={at={(rel axis cs:0,0,0.5)}, rotate=90, anchor=south},
    set layers
  ]


\addplot3 [samples=2, samples y=0, domain=0:3] (x, {1.5*(x-0.5)+3}, 0);
\addplot3 [cyan!50!black, thick] (0.5, x, {normal(x, 3, 0.5)});
\addplot3 [cyan!50!black, thick] (1.5, x, {normal(x, 4.5, 1)});
\addplot3 [cyan!50!black, thick] (2.5, x, {normal(x, 6, 1.5)});

\pgfplotsextra{
\begin{pgfonlayer}{axis background}
\draw [on layer=axis background] (0.5, 3, 0) -- (0.5, 3, {normal(0,0,0.5)}) (0.5,0,0) -- (0.5,12,0);
\draw (1.5, 4.5, 0) -- (1.5, 4.5, {normal(0,0,1)}) (1.5,0,0) -- (1.5,12,0);
\draw (2.5, 6, 0) -- (2.5, 6, {normal(0,0,1.5)}) (2.5,0,0) -- (2.5,12,0);
\end{pgfonlayer}
}
\end{axis}


\end{tikzpicture}

\end{document}

Here's a version with a different viewpoint and dots that are randomly distributed using a normal distribution with a varying standard deviation (using the approach used in Plotting a 2D gaussian sample):

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\makeatletter
        \pgfdeclareplotmark{dot}
        {%
            \fill circle [x radius=0.02, y radius=0.08];
        }%
\makeatother

\begin{document}

\begin{tikzpicture}[ % Define Normal Probability Function
declare function={
            normal(\x,\m,\s) = 1/(2*\s*sqrt(pi))*exp(-(\x-\m)^2/(2*\s^2));
        },
    declare function={invgauss(\a,\b) = sqrt(-2*ln(\a))*cos(deg(2*pi*\b));}
       ]
\begin{axis}[
    %no markers,
    domain=0:12,
    zmin=0, zmax=1,
    xmin=0, xmax=3,
    samples=200,
   samples y=0,
    view={40}{30},
    axis lines=middle,
    enlarge y limits=false,
    xtick={0.5,1.5,2.5},
    xmajorgrids,
    xticklabels={},
    ytick=\empty,
    xticklabels={$x_1$, $x_2$, $x_3$},
    ztick=\empty,
    xlabel=$x$, xlabel style={at={(rel axis cs:1,0,0)}, anchor=west},
    ylabel=$y$, ylabel style={at={(rel axis cs:0,1,0)}, anchor=south west},
    zlabel=Probability density, zlabel style={at={(rel axis cs:0,0,0.5)}, rotate=90, anchor=south},
    set layers, mark=cube
  ]

\addplot3 [gray!50, only marks, mark=dot, mark layer=like plot, samples=200, domain=0.1:2.9, on layer=axis background] (x, {1.5*(x-0.5)+3+invgauss(rnd,rnd)*x}, 0);
\addplot3 [samples=2, samples y=0, domain=0:3] (x, {1.5*(x-0.5)+3}, 0);
\addplot3 [cyan!50!black, thick] (0.5, x, {normal(x, 3, 0.5)});
\addplot3 [cyan!50!black, thick] (1.5, x, {normal(x, 4.5, 1)});
\addplot3 [cyan!50!black, thick] (2.5, x, {normal(x, 6, 1.5)});

\pgfplotsextra{
\begin{pgfonlayer}{axis background}
\draw [gray, on layer=axis background] (0.5, 3, 0) -- (0.5, 3, {normal(0,0,0.5)}) (0.5,0,0) -- (0.5,12,0)
    (1.5, 4.5, 0) -- (1.5, 4.5, {normal(0,0,1)}) (1.5,0,0) -- (1.5,12,0)
    (2.5, 6, 0) -- (2.5, 6, {normal(0,0,1.5)}) (2.5,0,0) -- (2.5,12,0);

\end{pgfonlayer}
}
\end{axis}


\end{tikzpicture}

\end{document}

And using a phenomenon that's discrete in x:

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\makeatletter
        \pgfdeclareplotmark{dot}
        {%
            \fill circle [x radius=0.08, y radius=0.32];
        }%
\makeatother

\begin{document}

\begin{tikzpicture}[ % Define Normal Probability Function
declare function={
            normal(\x,\m,\s) = 1/(2*\s*sqrt(pi))*exp(-(\x-\m)^2/(2*\s^2));
        },
    declare function={invgauss(\a,\b) = sqrt(-2*ln(\a))*cos(deg(2*pi*\b));}
       ]
\begin{axis}[
    %no markers,
    domain=0:12,
    zmin=0, zmax=1,
    xmin=0, xmax=3,
    samples=200,
   samples y=0,
    view={40}{30},
    axis lines=middle,
    enlarge y limits=false,
    xtick={0.5,1.5,2.5},
    xmajorgrids,
    xticklabels={},
    ytick=\empty,
    xticklabels={$x_1$, $x_2$, $x_3$},
    ztick=\empty,
    xlabel=$x$, xlabel style={at={(rel axis cs:1,0,0)}, anchor=west},
    ylabel=$y$, ylabel style={at={(rel axis cs:0,1,0)}, anchor=south west},
    zlabel=Probability density, zlabel style={at={(rel axis cs:0,0,0.5)}, rotate=90, anchor=south},
    set layers, mark=cube
  ]

\pgfplotsinvokeforeach{0.5,1.5,2.5}{
\addplot3 [draw=none, fill=black, opacity=0.25, only marks, mark=dot, mark layer=like plot, samples=30, domain=0.1:2.9, on layer=axis background] (#1, {1.5*(#1-0.5)+3+invgauss(rnd,rnd)*#1}, 0);
}
\addplot3 [samples=2, samples y=0, domain=0:3] (x, {1.5*(x-0.5)+3}, 0);
\addplot3 [cyan!50!black, thick] (0.5, x, {normal(x, 3, 0.5)});
\addplot3 [cyan!50!black, thick] (1.5, x, {normal(x, 4.5, 1)});
\addplot3 [cyan!50!black, thick] (2.5, x, {normal(x, 6, 1.5)});

\pgfplotsextra{
\begin{pgfonlayer}{axis background}
\draw [gray, on layer=axis background] (0.5, 3, 0) -- (0.5, 3, {normal(0,0,0.5)}) (0.5,0,0) -- (0.5,12,0)
    (1.5, 4.5, 0) -- (1.5, 4.5, {normal(0,0,1)}) (1.5,0,0) -- (1.5,12,0)
    (2.5, 6, 0) -- (2.5, 6, {normal(0,0,1.5)}) (2.5,0,0) -- (2.5,12,0);

\end{pgfonlayer}
}
\end{axis}


\end{tikzpicture}

\end{document}
  • 2
    Simply awesome!!! Excellent – MYaseen208 Jul 9 '15 at 12:41
  • For new version, I guess the distribution of data points should be along y-axis for each level of x. Isn't it? No data point between two consecutive x levels. – MYaseen208 Jul 9 '15 at 13:47
  • @MYaseen208: It depends on whether you assume the phenomenon shown to be continuous or discrete. The plot shows a continuous phenomenon, with the distribution shown at three different levels. – Jake Jul 9 '15 at 13:51
  • Would be nice if you also provide the graph when x is discrete. Thanks – MYaseen208 Jul 9 '15 at 13:55
  • 1
    @MYaseen208: Done – Jake Jul 9 '15 at 14:01
20

Here a pure tikz solution just for fun. At its current state the code needs some manual math to get the coordinates for the helper lines right if you want to change the normal function's parameters.

\documentclass[tikz, border=6mm]{standalone}

\newcommand{\normal}[2]{{\x},{(1/sqrt(2*pi*#2^2))*exp(-(\x-#1)^2/(2*#2^2))}}

\begin{document}
  \begin{tikzpicture}[x={(.5,0,-1)}, % y-axis
                      y={(0,1,0)}, 
                      z={(2,-.25,2)}, % x-axis
                      thick]

  \begin{scope}[>=latex, ->, xshift=-3cm, yshift=-.5cm]
    \draw (0,0,0) -- ++(5,0,0) node [right] {$y$};
    \draw (0,0,0) -- ++(0,2,0) node [above] {$f(u)$};
    \draw (0,0,0) -- ++(0,0,8) node [right] {$x$};
  \end{scope}

  \begin{scope}[smooth]
    \draw [domain=-2:2] plot (\normal{0}{.2});
    \draw [domain=-2:2, xshift=2cm, yshift=-.5cm] plot (\normal{.5}{.5});
    \draw [domain=-2:2, xshift=4cm, yshift=-1cm] plot (\normal{1}{1});
  \end{scope}

  \draw [shorten <=-1.45cm] (0,0,0) -- (1,0,4) node [font=\scriptsize, below right] {$\beta_1+\beta2X_i$};
  \foreach \x\m\y\l in {0/0/2/x_1,2/.5/.8/x_2,4/1/.4/x_i} {
    \draw (-2,0,\x) -- ++(4,0,0) node [below, at start] {$\l$};
    \draw (\m,0,\x) --++(0,\y,0);
  }
  \end{tikzpicture}
\end{document}

rendered image

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.