distplot/kdeplot如何计算kde曲线?
How does distplot/kdeplot calculate the kde curve?
我正在使用 seaborn 绘制数据。一切都很好,直到我的导师问我如何在下面的代码中绘制情节。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
x = np.random.normal(size=100)
sns.distplot(x)
plt.show()
这段代码的结果是:
我的问题:
distplot
是如何策划的?
为什么剧情从-3
开始到4
结束?
是否有任何参数函数或任何特定的数学函数 distplot
用来绘制这样的数据?
我使用 distplot
和 kind='kde'
来绘制我的数据,但我想知道这些函数背后的数学是什么。
这里有一些代码试图说明 kde 曲线是如何绘制的。
代码以 100 xs 的随机样本开始。
这些 xs 显示在 histogram 中。使用 density=True
时,直方图被归一化,因此它的整个面积为 1。(标准情况下,直方图的条形随着点数的增加而增长。在内部,计算整个面积,每个条形的高度除以该面积.)
要绘制 kde, a gaussian "bell" 曲线是围绕 N 个样本中的每一个绘制的。将这些曲线相加,并通过除以 N 进行归一化。
这些曲线的 sigma
是一个自由参数。默认情况下,它是根据 Scott 规则计算的(N ** (-1/5)
或 0.4
100 个点,示例图中的绿色曲线)。
下面的代码显示了 sigma
的不同选择的结果。较小的 sigma
s 包含更强的给定数据,较大的 sigma
s 显得更平滑。 sigma
没有完美的选择,它在很大程度上取决于数据和关于底层分布的已知(或猜测)内容。
import matplotlib.pyplot as plt
import numpy as np
def gauss(x, mu, sigma):
return np.exp(-((x - mu) / sigma) ** 2 / 2) / (sigma * np.sqrt(2 * np.pi))
N = 100
xs = np.random.normal(0, 1, N)
plt.hist(xs, density=True, label='Histogram', alpha=.4, ec='w')
x = np.linspace(xs.min() - 1, xs.max() + 1, 100)
for sigma in np.arange(.2, 1.2, .2):
plt.plot(x, sum(gauss(x, xi, sigma) for xi in xs) / N, label=f'$\sigma = {sigma:.1f}$')
plt.xlim(x[0], x[-1])
plt.legend()
plt.show()
PS:代替直方图或kde,其他可视化100个随机数的方法是一组短线:
plt.plot(np.repeat(xs, 3), np.tile((0, -0.05, np.nan), N), lw=1, c='k', alpha=0.5)
plt.ylim(ymin=-0.05)
或点(抖动,因此它们不重叠):
plt.scatter(xs, -np.random.rand(N)/10, s=1, color='crimson')
plt.ylim(ymin=-0.099)
我正在使用 seaborn 绘制数据。一切都很好,直到我的导师问我如何在下面的代码中绘制情节。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
x = np.random.normal(size=100)
sns.distplot(x)
plt.show()
这段代码的结果是:
我的问题:
distplot
是如何策划的?为什么剧情从
-3
开始到4
结束?是否有任何参数函数或任何特定的数学函数
distplot
用来绘制这样的数据?
我使用 distplot
和 kind='kde'
来绘制我的数据,但我想知道这些函数背后的数学是什么。
这里有一些代码试图说明 kde 曲线是如何绘制的。
代码以 100 xs 的随机样本开始。
这些 xs 显示在 histogram 中。使用 density=True
时,直方图被归一化,因此它的整个面积为 1。(标准情况下,直方图的条形随着点数的增加而增长。在内部,计算整个面积,每个条形的高度除以该面积.)
要绘制 kde, a gaussian "bell" 曲线是围绕 N 个样本中的每一个绘制的。将这些曲线相加,并通过除以 N 进行归一化。
这些曲线的 sigma
是一个自由参数。默认情况下,它是根据 Scott 规则计算的(N ** (-1/5)
或 0.4
100 个点,示例图中的绿色曲线)。
下面的代码显示了 sigma
的不同选择的结果。较小的 sigma
s 包含更强的给定数据,较大的 sigma
s 显得更平滑。 sigma
没有完美的选择,它在很大程度上取决于数据和关于底层分布的已知(或猜测)内容。
import matplotlib.pyplot as plt
import numpy as np
def gauss(x, mu, sigma):
return np.exp(-((x - mu) / sigma) ** 2 / 2) / (sigma * np.sqrt(2 * np.pi))
N = 100
xs = np.random.normal(0, 1, N)
plt.hist(xs, density=True, label='Histogram', alpha=.4, ec='w')
x = np.linspace(xs.min() - 1, xs.max() + 1, 100)
for sigma in np.arange(.2, 1.2, .2):
plt.plot(x, sum(gauss(x, xi, sigma) for xi in xs) / N, label=f'$\sigma = {sigma:.1f}$')
plt.xlim(x[0], x[-1])
plt.legend()
plt.show()
PS:代替直方图或kde,其他可视化100个随机数的方法是一组短线:
plt.plot(np.repeat(xs, 3), np.tile((0, -0.05, np.nan), N), lw=1, c='k', alpha=0.5)
plt.ylim(ymin=-0.05)
或点(抖动,因此它们不重叠):
plt.scatter(xs, -np.random.rand(N)/10, s=1, color='crimson')
plt.ylim(ymin=-0.099)