# 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, 2015 at 12:05
• Certainly very similar. Thank You. Although a representation in three dimensions is much more elegant. Jul 9, 2015 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. Jul 9, 2015 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 Jul 9, 2015 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. Jul 9, 2015 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, 2015 at 13:51
• Would be nice if you also provide the graph when x is discrete. Thanks Jul 9, 2015 at 13:55
• @MYaseen208: Done
– Jake
Jul 9, 2015 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}[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}


• Cool!...Can you add the X points like in the previous examples?
– JPMD
Nov 29, 2021 at 19:48