如何获得最大密度的坐标

时间:2019-10-25 13:52:11

标签: python python-3.x matplotlib scipy gaussian

如何获得密度最大的空间中的点的坐标。

enter image description here

我有这段代码可以生成一个随机点并从该点进行密度分析。

import numpy as np
from scipy import stats
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

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

x_data = random_data(50)
y_data = random_data(50)

kernel = stats.gaussian_kde(np.vstack([x_data, y_data]), bw_method=0.05)

b = plt.plot(x_data, y_data, 'ro')
df = pd.DataFrame({"x":x_data,"y":y_data})
p = sns.jointplot(data=df,x='x', y='y',kind='kde')

plt.show(p)

感谢您的帮助。 :)

1 个答案:

答案 0 :(得分:1)

对于初学者,让我说一下显而易见的一点:sns.jointplot自己计算内核密度,因此您的kernel变量尚未使用。

这是sns.jointplot为我生成的一个随机样本: fancy 2d kernel density contour with marginal distributions

在(7,5.4)附近有一个很好的最大值。

您的kernel对应于以下内容:

x,y = np.mgrid[:10:100j, :10:100j]  # 100 x 100 grid for plotting
z = kernel.pdf(np.array([x.ravel(),y.ravel()])).reshape(x.shape)

fig,ax = plt.subplots()
ax.contourf(x, y, z, levels=10)
ax.axis('scaled')

output from original kernel's KDE: scattered sharp peaks around input points

显然不是这样:密度包含以输入点为中心的峰;您将永远无法获得sns.jointplot所提供的估算值。

我们可以轻松解决此问题:您只需在对bw_method的调用中删除自定义gaussian_kde参数:

kernel = stats.gaussian_kde(np.vstack([x_data, y_data]))

x,y = np.mgrid[:10:100j, :10:100j]  # 100 x 100 grid for plotting
z = kernel.pdf(np.array([x.ravel(),y.ravel()])).reshape(x.shape)

fig,ax = plt.subplots()
ax.contourf(x, y, z, levels=10)
ax.axis('scaled')

这看起来就是您想要的方式: fixed contour plot which looks like the one from sns.jointplot

现在,您知道这个kernel.pdf是一个双变量函数,您正在为其寻求最大值。

要找到最大值,您可能应该使用scipy.optimize中的某个值,例如scipy.optimize.minimize(技巧是查看函数的负数,它将最大值变为最小值)。

由于您的函数可能会有一些局部最大值,因此可靠地找到全局最大值并非易事。我要么使用上述的minimize,要么首先在相关域上使用稀疏网格,然后首先找到最佳的最大候选值,或者 或使用诸如{{3} },这是一种随机求解器,应该能够很好地发现函数的真实全局最小值。

寻找和最小化根源始终是善变的业务,因此您将不得不动用真实数据和可用方法来寻找可靠的工作流程,从而为您提供最大的收益。