# Kernel density estimation bandwidth

I'm trying to reimplement ScipPy's gaussian_kde to understand how exactly the estimation works so that I can reimplement it in C++ later. I'm following this article and I assumed that I just need to sum a number of gaussians and that's my result.

My code:

points = np.array([3.0, 4.0, 6.0], dtype=float)

def gaussian_kernel(u):
return np.exp(-0.5 * u**2) / np.sqrt(2 * np.pi)

bw = 0.6

x = np.linspace(0, 10, 100)
y = np.zeros_like(x)
for i in points:
g = gaussian_kernel((x - i) / bw) / len(points)
plt.plot(x, g, alpha=0.1)
y += g
plt.plot(x, y)

kde = gaussian_kde(points, bw_method=bw)
plt.plot(x, kde(x))

However, I realized that the bandwith factor in gaussian_kde doesn't do what I expected it to do and I'm getting results like this:

Scaling of the gaussians in my code is clearly wrong, but also the width of the gaussians in gaussian_kde depends on the number of points in the data set. I have tried reading the code, but the math is a bit above my head (I'm not very familiar with statistics).

Can someone explain what exactly does the bw_factor parameter mean and how does it affect the individual gaussians?

• Could you explain what your graphic is showing and why it does not seem reasonable? – whuber Feb 12 '17 at 19:53
• My goal is that the lines are the same, i.e. my y is exactly the same as kde(x), but in the picture you can see that SciPy's KDE (purple) is more smooth than mine (cyan) and also it's higher. I guess I'm missing some scaling somewhere, but I don't see where. – Lukáš Lalinský Feb 12 '17 at 19:57
• It's clear you are using a narrower bandwidth than employed for the purple line and that your scaling is incorrect. The scaling is incorrect because you are not incorporating the effect of the changeable bandwidth in the definition of the kernel. Nothing can be said concerning the choice of bandwidth, because you haven't explained where it came from or how it compares to that of the purple KDE. – whuber Feb 12 '17 at 20:47