4

I have a simple code that generates a 2D gaussian kernel using scipy.stats.gaussian_kde function.

Here's the MWE:

def random_data(N):
    # Generate some random data.
    return np.random.uniform(0., 10., N)

# Data lists.
x_data = random_data(10000)
y_data = random_data(10000)

# Obtain the KDE for this region.
kernel = stats.gaussian_kde(np.vstack([x_data, y_data]), bw_method=0.05)

and here's the result:

enter image description here

What I need is a way to obtain the x,y coordinates of the maximum value in this KDE.

For what I could gather from various sources the direct way to locate the maximum value seem to be evaluating the kernel on a fine grid and then just use np.argmax to find it, see below:

# define grid.
xmin, xmax = min(x_data), max(x_data)
ymin, ymax = min(y_data), max(y_data)
x, y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([x.ravel(), y.ravel()])

# THIS IS TOO SLOW.
k_pos = kernel(positions)

# Print max value.
print k_pos[np.argmax(k_pos)]

# Print x,y coordinates of max value.
print positions.T[np.argmax(k_pos)]

The issue with this is that evaluating the kernel is terribly slow, almost to the point of being unusable for not too large datasets.

Is there a better way to get the coordinates of the max value?

Also accepted (perhaps even better since it would also allow fast plotting): is there a faster way to evaluate the kernel in a fine grid?

Gabriel
  • 40,504
  • 73
  • 230
  • 404
  • 1
    If you bin your data first, then you can use convolution and fft. statsmodels fft based KDE only works for 1d, but there are 2d recipes in python available. – Josef Mar 27 '14 at 17:12
  • @user333700 Binning the data would result in a loss of precision in the end coordinates. – Gabriel Apr 07 '14 at 19:15
  • use `np.unravel_index(np.argmax(k), k.shape)` to get the coordinates from the argmax – endolith Apr 12 '14 at 02:03

1 Answers1

-1
np.argmax(kernel)

might be what you're looking for...

see: http://docs.scipy.org/doc/numpy/reference/generated/numpy.argmax.html

asPlankBridge
  • 1,032
  • 1
  • 17
  • 30