# How to make a graph of heteroskedasticity with TikZ/PGF?

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

• 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

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}
{%
}%
\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}
{%
}%
\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}

• 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
• @MYaseen208: Done – Jake Jul 9 '15 at 14:01

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}{{\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} 