【问题标题】:How to draw a matching Bell curve over a histogram?如何在直方图上绘制匹配的贝尔曲线?
【发布时间】:2020-05-01 10:45:27
【问题描述】:

到目前为止,我的代码,我对编程非常陌生,并且已经尝试了一段时间。

在这里,我将Box-Muller transform 应用于从random uniform 采样开始的近似两个Gaussian normal distributions。然后,我为它们创建了一个直方图。

现在,我想将获得的直方图与“真实的东西”进行比较:标准Bell curve。如何绘制这样的曲线来匹配直方图?

import numpy as np
import matplotlib.pyplot as plt

N = 10000
z1 = np.random.uniform(0, 1.0, N)
z2 = np.random.uniform(0, 1.0, N)

R_sq = -2 * np.log(z1)
theta = 2 * np.pi * z2
z1 = np.sqrt(R_sq) * np.cos(theta)
z2 = np.sqrt(R_sq) * np.sin(theta)

fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
ax.hist(z1, bins=40, range=(-4, 4), color='red')
plt.title("Histgram")
plt.xlabel("z1")
plt.ylabel("frequency")
ax2 = fig.add_subplot(2, 1, 2)
ax2.hist(z2, bins=40, range=(-4, 4), color='blue')
plt.xlabel("z2")
plt.show()

【问题讨论】:

  • 请说出发生了什么,包括任何错误消息。还有你得到了什么结果,你期待什么。谢谢。
  • 该代码工作正常,并给出了一个很好的正态分布直方图图。我只是根本不知道如何拟合高斯曲线。

标签: python numpy matplotlib


【解决方案1】:

为了获得“核密度估计”,scipy.stats.gaussian_kde 计算了一个函数来拟合数据。

仅绘制高斯正态曲线,有 [scipy.stats.norm]。减去mean并除以standard deviation,使位置适应给定的数据。

将绘制两条曲线,使曲线下方的面积总和为 1。为了将它们调整为直方图的大小,这些曲线需要按数据长度乘以 bin 宽度来缩放。或者,此缩放可以保持为 1,并通过添加参数 hist(..., density=True) 来缩放直方图。

在演示代码中,数据被截断以说明 kde 和高斯法线之间的差异。

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats

x = np.linspace(-4,4,1000)
N = 10000
z1 = np.random.randint(1, 3, N) * np.random.uniform(0, .4, N)
z2 = np.random.uniform(0, 1, N)

R_sq = -2 * np.log(z1)
theta = 2 * np.pi * z2
z1 = np.sqrt(R_sq) * np.cos(theta)
z2 = np.sqrt(R_sq) * np.sin(theta)

fig = plt.figure(figsize=(12,4))
for ind_subplot, zi, col in zip((1, 2), (z1, z2), ('crimson', 'dodgerblue')):
    ax = fig.add_subplot(1, 2, ind_subplot)
    ax.hist(zi, bins=40, range=(-4, 4), color=col, label='histogram')
    ax.set_xlabel("z"+str(ind_subplot))
    ax.set_ylabel("frequency")

    binwidth = 8 / 40
    scale_factor = len(zi) * binwidth

    gaussian_kde_zi = stats.gaussian_kde(z1)
    ax.plot(x, gaussian_kde_zi(x)*scale_factor, color='springgreen', linewidth=3, label='kde')

    std_zi = np.std(zi)
    mean_zi = np.mean(zi)
    ax.plot(x, stats.norm.pdf((x-mean_zi)/std_zi)*scale_factor, color='black', linewidth=2, label='normal')
    ax.legend()

plt.show()

z1 和 z2 的原始值非常类似于正态分布,因此黑线(数据的高斯正态)和绿线(KDE)非常相似。

当前代码首先计算数据的真实均值和真实标准差。当您想模拟完美的高斯法线时,您应该与均值为零和标准差为 1 的曲线进行比较。你会发现它们在情节上几乎相同。

【讨论】:

  • 我仍然对某些行的作用感到困惑。但我会查一下。您是否还更改了第一个 z1 和 z2 值以显示 kde 和正常之间的更大差异?任何方法,非常感谢你
  • 是的,我只更改了 z1/z2 以显示曲线之间的差异。在原始版本中,曲线几乎一起落下。这是合乎逻辑的,因为您正在尝试模仿正态分布。绿线是一个试图适应直方图的平滑函数。黑线将是完美的高斯正态分布。
  • 参见this interesting article,了解 KDE。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
相关资源
最近更新 更多